diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..4f8fb4f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +node_modules +dist +jest.config.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..4afa5b0 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,17 @@ +{ + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 12, + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + "rules": {}, + "env": { + "es2021": true + } +} diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..435f64a --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "semi": false, + "singleQuote": false, + "arrowParens": "avoid" +} diff --git a/jest.config.js b/jest.config.js index 39ee932..d86d036 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,14 +1,10 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', + preset: "ts-jest", + testEnvironment: "node", collectCoverage: true, - coverageDirectory: 'coverage', - testPathIgnorePatterns: [ - '/node_modules/', - ], - preset: 'ts-jest', - roots: [ - '/src', - ] -}; + coverageDirectory: "coverage", + testPathIgnorePatterns: ["/node_modules/"], + preset: "ts-jest", + roots: ["/src"], +} diff --git a/package-lock.json b/package-lock.json index 95986a6..e546632 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,12 @@ }, "devDependencies": { "@types/jest": "29.5.9", + "@typescript-eslint/eslint-plugin": "6.13.2", + "@typescript-eslint/parser": "6.13.2", + "eslint": "8.55.0", + "eslint-config-prettier": "9.1.0", "pino-pretty": "10.2.3", + "prettier": "3.1.0", "ts-jest": "29.1.1" } }, @@ -35,6 +40,15 @@ "typescript-json-schema": "0.62.0" } }, + "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.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -725,6 +739,162 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", + "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1090,6 +1260,41 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -6941,6 +7146,12 @@ "pretty-format": "^29.0.0" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/node": { "version": "20.10.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", @@ -6958,6 +7169,12 @@ "form-data": "^4.0.0" } }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -6979,138 +7196,440 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", + "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", + "dev": true, "dependencies": { - "event-target-shim": "^5.0.0" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/type-utils": "6.13.2", + "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "bin": { - "acorn": "bin/acorn" + "node": "^16.0.0 || >=18.0.0" }, - "engines": { - "node": ">=0.4.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "node_modules/@typescript-eslint/eslint-plugin/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": ">=0.4.0" + "node": ">=10" } }, - "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, "dependencies": { - "humanize-ms": "^1.2.1" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">= 8.0.0" + "node": ">=10" } }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", + "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", + "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dependencies": { - "ajv": "^8.0.0" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "ajv": "^8.0.0" + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "ajv": { + "typescript": { "optional": true } } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, - "peer": true, "dependencies": { - "type-fest": "^0.21.3" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" }, "engines": { - "node": ">=8" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", + "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", "dev": true, - "peer": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/utils": "6.13.2", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@typescript-eslint/types": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, - "peer": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">= 8" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" - }, + "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/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/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.13.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "peer": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -7121,6 +7640,15 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -7282,7 +7810,6 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7390,7 +7917,6 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "peer": true, "engines": { "node": ">=6" } @@ -7554,8 +8080,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -7596,7 +8121,6 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, - "peer": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -7628,7 +8152,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "peer": true, "dependencies": { "ms": "2.1.2" }, @@ -7656,6 +8179,12 @@ } } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -7710,6 +8239,30 @@ "md5": "^2.3.0" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dotenv": { "version": "16.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", @@ -7783,21 +8336,300 @@ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "engines": { - "node": ">=8" + "node": ">=8" + } + }, + "node_modules/eslint": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", + "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.55.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "peer": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/event-target-shim": { @@ -7877,12 +8709,46 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "node_modules/fast-redact": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", @@ -7905,6 +8771,15 @@ "node": ">= 4.9.1" } }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -7915,6 +8790,18 @@ "bser": "2.1.1" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -7941,6 +8828,26 @@ "node": ">=8" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -8056,7 +8963,6 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, - "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -8072,6 +8978,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -8082,12 +9000,38 @@ "node": ">=4" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/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 }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -8216,6 +9160,40 @@ } ] }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -8241,7 +9219,6 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "peer": true, "engines": { "node": ">=0.8.19" } @@ -8285,6 +9262,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -8305,6 +9291,18 @@ "node": ">=6" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -8314,6 +9312,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -8331,8 +9338,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", @@ -9097,6 +10103,12 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "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", @@ -9109,6 +10121,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -9121,6 +10139,15 @@ "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, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -9141,6 +10168,19 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -9167,6 +10207,12 @@ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -9261,6 +10307,15 @@ "dev": true, "peer": true }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -9308,7 +10363,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -9334,8 +10388,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/node-domexception": { "version": "1.0.0", @@ -9471,12 +10524,28 @@ "undici-types": "~5.26.4" } }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -9526,6 +10595,18 @@ "node": ">=6" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -9550,7 +10631,6 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -9560,7 +10640,6 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -9570,7 +10649,6 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -9580,6 +10658,15 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -9682,6 +10769,30 @@ "node": ">=8" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -9774,6 +10885,26 @@ ], "peer": true }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/quick-format-unescaped": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", @@ -9875,6 +11006,54 @@ "node": ">=10" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -9923,7 +11102,6 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "peer": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -9936,7 +11114,6 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -10062,7 +11239,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -10140,6 +11316,12 @@ "node": ">=8" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "node_modules/thread-stream": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", @@ -10182,6 +11364,18 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-jest": { "version": "29.1.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", @@ -10300,6 +11494,18 @@ } } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -10443,7 +11649,6 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "peer": true, "dependencies": { "isexe": "^2.0.0" }, @@ -10550,7 +11755,6 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "peer": true, "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 4f58a30..4af4818 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@ "typecheck": "tsc -b tsconfig.json", "typecheck:watch": "tsc -b tsconfig.json --watch", "build": "tsc -b tsconfig.json", + "lint": "eslint --ignore-path .eslintignore --ext .js,.ts .", + "format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\"", "clean": "tsc -b tsconfig.json --clean", "test": "jest", "prepare": "npm run build", @@ -30,7 +32,12 @@ }, "devDependencies": { "@types/jest": "29.5.9", + "@typescript-eslint/eslint-plugin": "6.13.2", + "@typescript-eslint/parser": "6.13.2", + "eslint": "8.55.0", + "eslint-config-prettier": "9.1.0", "pino-pretty": "10.2.3", + "prettier": "3.1.0", "ts-jest": "29.1.1" } } diff --git a/schema.json b/schema.json index e79dc0c..46781b9 100644 --- a/schema.json +++ b/schema.json @@ -1,216 +1,189 @@ { - "$id": "https://andrefs.com/schemas/2023/SemMeasures", - "$schema": "http://json-schema.org/draft-07/schema#", - "definitions": { - "DatasetProfile": { - "properties": { - "id": { - "description": "An identifier for the dataset", - "type": "string" - }, - "metadata": { - "$ref": "https://andrefs.com/schemas/2023/SemMeasures#/definitions/Metadata", - "description": "Metadata for the dataset" - }, - "originalInstructions": { - "description": "The original instructions given to the annotators", - "type": "string" - }, - "partitions": { - "description": "The partitions containing the dataset data", - "items": { - "$ref": "https://andrefs.com/schemas/2023/SemMeasures#/definitions/Partition" - }, - "type": "array" - } - }, - "required": [ - "id", - "metadata", - "partitions" - ], - "type": "object" + "$id": "https://andrefs.com/schemas/2023/SemMeasures", + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "DatasetProfile": { + "properties": { + "id": { + "description": "An identifier for the dataset", + "type": "string" }, - "Metadata": { - "properties": { - "date": { - "description": "The date the dataset was published", - "pattern": "^[0-9]{4}(-[0-9]{2}(-[0-9]{2})?)?$", - "type": "string" - }, - "description": { - "description": "A description of the dataset", - "type": "string" - }, - "downloadUrls": { - "description": "URL(s) to download the dataset files", - "items": { - "format": "uri", - "type": "string" - }, - "type": "array" - }, - "measureTypes": { - "description": "Which type of measures are used to compare the words", - "items": { - "enum": [ - "relatedness", - "similarity" - ], - "type": "string" - }, - "type": "array" - }, - "name": { - "description": "The name of the dataset", - "type": "string" - }, - "papers": { - "description": "Information about the scientific papers describing the dataset", - "items": { - "$ref": "https://andrefs.com/schemas/2023/SemMeasures#/definitions/Paper" - }, - "type": "array" - }, - "urls": { - "description": "Web sites containing information about the dataset", - "items": { - "format": "uri", - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "date", - "description", - "downloadUrls", - "measureTypes", - "name", - "papers", - "urls" - ], - "type": "object" + "metadata": { + "$ref": "https://andrefs.com/schemas/2023/SemMeasures#/definitions/Metadata", + "description": "Metadata for the dataset" + }, + "originalInstructions": { + "description": "The original instructions given to the annotators", + "type": "string" + }, + "partitions": { + "description": "The partitions containing the dataset data", + "items": { + "$ref": "https://andrefs.com/schemas/2023/SemMeasures#/definitions/Partition" + }, + "type": "array" + } + }, + "required": ["id", "metadata", "partitions"], + "type": "object" + }, + "Metadata": { + "properties": { + "date": { + "description": "The date the dataset was published", + "pattern": "^[0-9]{4}(-[0-9]{2}(-[0-9]{2})?)?$", + "type": "string" }, - "Paper": { - "properties": { - "title": { - "description": "The title of the paper", - "type": "string" + "description": { + "description": "A description of the dataset", + "type": "string" + }, + "downloadUrls": { + "description": "URL(s) to download the dataset files", + "items": { + "format": "uri", + "type": "string" + }, + "type": "array" + }, + "measureTypes": { + "description": "Which type of measures are used to compare the words", + "items": { + "enum": ["relatedness", "similarity"], + "type": "string" + }, + "type": "array" + }, + "name": { + "description": "The name of the dataset", + "type": "string" + }, + "papers": { + "description": "Information about the scientific papers describing the dataset", + "items": { + "$ref": "https://andrefs.com/schemas/2023/SemMeasures#/definitions/Paper" + }, + "type": "array" + }, + "urls": { + "description": "Web sites containing information about the dataset", + "items": { + "format": "uri", + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "date", + "description", + "downloadUrls", + "measureTypes", + "name", + "papers", + "urls" + ], + "type": "object" + }, + "Paper": { + "properties": { + "title": { + "description": "The title of the paper", + "type": "string" + }, + "url": { + "description": "The URL where the paper can be found", + "format": "uri", + "type": "string" + } + }, + "required": ["title"], + "type": "object" + }, + "Partition": { + "properties": { + "data": { + "description": "The data for the partition", + "items": { + "$ref": "https://andrefs.com/schemas/2023/SemMeasures#/definitions/PartitionData" + }, + "type": "array" + }, + "id": { + "description": "An identifier for the partition", + "type": "string" + }, + "measureType": { + "description": "Which type of measure is used to compare the words", + "enum": ["relatedness", "similarity"], + "type": "string" + } + }, + "required": ["data", "id", "measureType"], + "type": "object" + }, + "PartitionData": { + "anyOf": [ + { + "allOf": [ + { + "properties": { + "word1": { + "description": "The first word in the pair", + "type": "string" }, - "url": { - "description": "The URL where the paper can be found", - "format": "uri", - "type": "string" + "word2": { + "description": "The second word in the pair", + "type": "string" } + }, + "required": ["word1", "word2"], + "type": "object" }, - "required": [ - "title" - ], - "type": "object" + { + "properties": { + "value": { + "description": "The averaged numeric value of the semantic measure for the pair", + "type": "number" + } + }, + "required": ["value"], + "type": "object" + } + ] }, - "Partition": { - "properties": { - "data": { - "description": "The data for the partition", - "items": { - "$ref": "https://andrefs.com/schemas/2023/SemMeasures#/definitions/PartitionData" - }, - "type": "array" + { + "allOf": [ + { + "properties": { + "word1": { + "description": "The first word in the pair", + "type": "string" }, - "id": { - "description": "An identifier for the partition", - "type": "string" - }, - "measureType": { - "description": "Which type of measure is used to compare the words", - "enum": [ - "relatedness", - "similarity" - ], - "type": "string" + "word2": { + "description": "The second word in the pair", + "type": "string" } + }, + "required": ["word1", "word2"], + "type": "object" }, - "required": [ - "data", - "id", - "measureType" - ], - "type": "object" - }, - "PartitionData": { - "anyOf": [ - { - "allOf": [ - { - "properties": { - "word1": { - "description": "The first word in the pair", - "type": "string" - }, - "word2": { - "description": "The second word in the pair", - "type": "string" - } - }, - "required": [ - "word1", - "word2" - ], - "type": "object" - }, - { - "properties": { - "value": { - "description": "The averaged numeric value of the semantic measure for the pair", - "type": "number" - } - }, - "required": [ - "value" - ], - "type": "object" - } - ] - }, - { - "allOf": [ - { - "properties": { - "word1": { - "description": "The first word in the pair", - "type": "string" - }, - "word2": { - "description": "The second word in the pair", - "type": "string" - } - }, - "required": [ - "word1", - "word2" - ], - "type": "object" - }, - { - "properties": { - "values": { - "description": "The individual numeric values of the semantic measure for the pair", - "items": { - "type": "number" - }, - "type": "array" - } - }, - "required": [ - "values" - ], - "type": "object" - } - ] + { + "properties": { + "values": { + "description": "The individual numeric values of the semantic measure for the pair", + "items": { + "type": "number" + }, + "type": "array" } - ] + }, + "required": ["values"], + "type": "object" + } + ] } + ] } + } } - diff --git a/src/lib/experiments/compare-mc30.ts b/src/lib/experiments/compare-mc30.ts index 89199a6..f08eade 100644 --- a/src/lib/experiments/compare-mc30.ts +++ b/src/lib/experiments/compare-mc30.ts @@ -1,152 +1,157 @@ -import mc30 from 'punuy-datasets/mc30'; -import rg65 from 'punuy-datasets/rg65'; -import ws353 from 'punuy-datasets/ws353'; -import pcorrtest from '@stdlib/stats-pcorrtest'; +import mc30 from "punuy-datasets/mc30" +import rg65 from "punuy-datasets/rg65" +import ws353 from "punuy-datasets/ws353" +import pcorrtest from "@stdlib/stats-pcorrtest" -import { Model, ModelIds, gpt35turbo, gpt4, gpt4turbo } from '../models' -import { JsonSyntaxError } from "../validation"; -import logger from '../logger'; +import { Model, ModelIds, gpt35turbo, gpt4, gpt4turbo } from "../models" +import { JsonSyntaxError } from "../validation" +import logger from "../logger" interface DatasetScores { [word1: string]: { [word2: string]: { - [dataset: string]: number; + [dataset: string]: number } } } type ModelsResults = { - [key in ModelIds]: string[]; + [key in ModelIds]: string[] } - export const loadDatasetScores = async () => { - const pairs: DatasetScores = {}; + const pairs: DatasetScores = {} for (const part of mc30.partitions) { for (const entry of part.data) { - pairs[entry.word1] = pairs[entry.word1] || {}; - pairs[entry.word1][entry.word2] = pairs[entry.word1][entry.word2] || {}; - if ('value' in entry) { - pairs[entry.word1][entry.word2]['mc30'] = entry.value; + pairs[entry.word1] = pairs[entry.word1] || {} + pairs[entry.word1][entry.word2] = pairs[entry.word1][entry.word2] || {} + if ("value" in entry) { + pairs[entry.word1][entry.word2]["mc30"] = entry.value } else { - pairs[entry.word1][entry.word2]['mc30'] = entry.values.reduce((a, b) => a + b, 0) / entry.values.length; + pairs[entry.word1][entry.word2]["mc30"] = + entry.values.reduce((a, b) => a + b, 0) / entry.values.length } } } for (const part of rg65.partitions) { for (const entry of part.data) { - const value = 'value' in entry ? entry.value : entry.values.reduce((a, b) => a + b, 0) / entry.values.length; + const value = + "value" in entry + ? entry.value + : entry.values.reduce((a, b) => a + b, 0) / entry.values.length if (entry.word1 in pairs && entry.word2 in pairs[entry.word1]) { - pairs[entry.word1][entry.word2][rg65.id] = value; + pairs[entry.word1][entry.word2][rg65.id] = value } else if (entry.word2 in pairs && entry.word1 in pairs[entry.word2]) { - pairs[entry.word2][entry.word1][rg65.id] = value; + pairs[entry.word2][entry.word1][rg65.id] = value } } } for (const part of ws353.partitions) { for (const entry of part.data) { - const value = 'value' in entry ? entry.value : entry.values.reduce((a, b) => a + b, 0) / entry.values.length; + const value = + "value" in entry + ? entry.value + : entry.values.reduce((a, b) => a + b, 0) / entry.values.length if (entry.word1 in pairs && entry.word2 in pairs[entry.word1]) { - pairs[entry.word1][entry.word2][ws353.id] = value * (4 / 10); + pairs[entry.word1][entry.word2][ws353.id] = value * (4 / 10) } else if (entry.word2 in pairs && entry.word1 in pairs[entry.word2]) { - pairs[entry.word2][entry.word1][ws353.id] = value * (4 / 10); + pairs[entry.word2][entry.word1][ws353.id] = value * (4 / 10) } } } // chord vs cord // see http://dx.doi.org/10.1162/coli.2006.32.1.13 - delete pairs['chord']; + delete pairs["chord"] - return pairs; + return pairs } const getPairs = (scores: DatasetScores) => { - const pairs: [string, string][] = []; + const pairs: [string, string][] = [] for (const word1 in scores) { for (const word2 in scores[word1]) { - pairs.push([word1, word2]); + pairs.push([word1, word2]) } } - return pairs; + return pairs } - -const name = 'compare-mc30'; -const description = 'Compare the scores of multiple AI models with the scores from multiple human annotations of the MC30 pair set.'; +const name = "compare-mc30" +const description = + "Compare the scores of multiple AI models with the scores from multiple human annotations of the MC30 pair set." const genPrompt = (pairs: string[][]) => 'Please rate the similarity of the following pairs of words on a scale of 0 to 4, where 0 means "completely unrelated" and 4 means "very similar". Fractional values are allowed.\n\n' + - pairs.map(([w1, w2]) => `${w1} ${w2}`).join('\n'); - - + pairs.map(([w1, w2]) => `${w1} ${w2}`).join("\n") // TODO fix when OpenAI supports items with tuple definition in JSON schema // https://community.openai.com/t/json-schema-tuple-validation-support/273554 const resultSchema = { - "type": "object", - "properties": { - "scores": { - "type": "array", - "items": { - "type": "object", - "properties": { - "words": { "type": "array", "items": { "type": "string" } }, - "score": { "type": "number" } - } - } - } - } + type: "object", + properties: { + scores: { + type: "array", + items: { + type: "object", + properties: { + words: { type: "array", items: { type: "string" } }, + score: { type: "number" }, + }, + }, + }, + }, } async function runTrialModel(model: Model, prompt: string) { const f = { - name: 'evaluate_scores', - description: 'Evaluate the word similarity scores.', - parameters: resultSchema - }; + name: "evaluate_scores", + description: "Evaluate the word similarity scores.", + parameters: resultSchema, + } - const res = await model.makeRequest(prompt, { function: f }); - return res; + const res = await model.makeRequest(prompt, { function: f }) + return res } async function runTrialsModel(trials: number, model: Model, prompt: string) { - logger.info(` model ${model.modelId}.`); - logger.debug(`Prompt: ${prompt}`); - const results = []; + logger.info(` model ${model.modelId}.`) + logger.debug(`Prompt: ${prompt}`) + const results = [] for (let i = 0; i < trials; i++) { logger.info(` trial #${i + 1} of ${trials}`) - const res = await runTrialModel(model, prompt); - results.push(res.type === 'openai' ? res.data.choices[0].message.tool_calls?.[0].function.arguments || '' : ''); + const res = await runTrialModel(model, prompt) + results.push( + res.type === "openai" + ? res.data.choices[0].message.tool_calls?.[0].function.arguments || "" + : "", + ) } - return results; + return results } async function runTrials(trials: number) { - const scores = await loadDatasetScores(); - const pairs = getPairs(scores); - const prompt = genPrompt(pairs); - - const models = [gpt35turbo, gpt4, gpt4turbo]; - logger.info(`Running experiment ${name} ${trials} times.`); + const scores = await loadDatasetScores() + const pairs = getPairs(scores) + const prompt = genPrompt(pairs) - const gpt35turbo_res = await runTrialsModel(trials, gpt35turbo, prompt); - const gpt4_res = await runTrialsModel(trials, gpt4, prompt); - const gpt4turbo_res = await runTrialsModel(trials, gpt4turbo, prompt); + logger.info(`Running experiment ${name} ${trials} times.`) + const gpt35turbo_res = await runTrialsModel(trials, gpt35turbo, prompt) + const gpt4_res = await runTrialsModel(trials, gpt4, prompt) + const gpt4turbo_res = await runTrialsModel(trials, gpt4turbo, prompt) return { gpt35turbo: gpt35turbo_res, gpt4: gpt4_res, - gpt4turbo: gpt4turbo_res + gpt4turbo: gpt4turbo_res, } - } interface MC30Results { @@ -154,18 +159,17 @@ interface MC30Results { [word2: string]: { models: { [model: string]: { - avg: number; - values: number[]; - sum: number; - count: number; + avg: number + values: number[] + sum: number + count: number } - }, + } human: { - [dataset: string]: number; + [dataset: string]: number } } } - } function unzipResults(results: MC30Results) { @@ -175,136 +179,141 @@ function unzipResults(results: MC30Results) { gpt4turbo: [] as number[], mc30: [] as number[], rg65: [] as number[], - ws353: [] as number[] - }; + ws353: [] as number[], + } for (const w1 in results) { for (const w2 in results[w1]) { - res.gpt35turbo.push(results[w1][w2].models.gpt35turbo.avg); - res.gpt4.push(results[w1][w2].models.gpt4.avg); - res.gpt4turbo.push(results[w1][w2].models.gpt4turbo.avg); - res.mc30.push(results[w1][w2].human.mc30); - res.rg65.push(results[w1][w2].human.rg65); - res.ws353.push(results[w1][w2].human.ws353); + res.gpt35turbo.push(results[w1][w2].models.gpt35turbo.avg) + res.gpt4.push(results[w1][w2].models.gpt4.avg) + res.gpt4turbo.push(results[w1][w2].models.gpt4turbo.avg) + res.mc30.push(results[w1][w2].human.mc30) + res.rg65.push(results[w1][w2].human.rg65) + res.ws353.push(results[w1][w2].human.ws353) } } - return res; + return res } - async function validate(modelsRes: ModelsResults, humanScores: DatasetScores) { try { - let res = mergeResults(modelsRes, humanScores); - let arrays = unzipResults(res); - let corrMat = calcCorrelation(Object.values(arrays)); + const res = mergeResults(modelsRes, humanScores) + const arrays = unzipResults(res) + const corrMat = calcCorrelation(Object.values(arrays)) - printMatrix(Object.keys(arrays), corrMat); + printMatrix(Object.keys(arrays), corrMat) } catch (e) { - return new JsonSyntaxError(); + return new JsonSyntaxError() } } -function printMatrix(varNames: string[], matrix: ReturnType[][]) { +function printMatrix( + varNames: string[], + matrix: ReturnType[][], +) { for (let i = 0; i < varNames.length - 1; i++) { for (let j = i + 1; j < varNames.length; j++) { - let r = matrix[i][j]; - console.log(`----------------------\n${varNames[i]} vs ${varNames[j]}`); - console.log(r.print()); + const r = matrix[i][j] + console.log(`----------------------\n${varNames[i]} vs ${varNames[j]}`) + console.log(r.print()) } } - console.log('\n\n,' + varNames.join(',')); + console.log("\n\n," + varNames.join(",")) for (let i = 0; i < varNames.length; i++) { - console.log([varNames[i], ...matrix[i].map((r) => r?.pcorr.toFixed(2))].join(',')); + console.log( + [varNames[i], ...matrix[i].map(r => r?.pcorr.toFixed(2))].join(","), + ) } - console.log('\n\n'); + console.log("\n\n") } - function calcCorrelation(data: number[][]) { - const corrMatrix = [] as ReturnType[][]; + const corrMatrix = [] as ReturnType[][] for (let i = 0; i < data.length; i++) { - corrMatrix[i] = []; + corrMatrix[i] = [] for (let j = 0; j < data.length; j++) { if (i < j) { - const corr = pcorrtest(data[i], data[j]); - corrMatrix[i][j] = corr; + const corr = pcorrtest(data[i], data[j]) + corrMatrix[i][j] = corr } } } - return corrMatrix; - + return corrMatrix } function mergeResults(modelsRes: ModelsResults, humanScores: DatasetScores) { - let res = {} as MC30Results; + const res = {} as MC30Results try { - const gpt35turbo = modelsRes.gpt35turbo.map((r) => JSON.parse(r)); // TODO cast to resultSchema somehow - const gpt4 = modelsRes.gpt4.map((r) => JSON.parse(r)); - const gpt4turbo = modelsRes.gpt4turbo.map((r) => JSON.parse(r)); + const gpt35turbo = modelsRes.gpt35turbo.map(r => JSON.parse(r)) // TODO cast to resultSchema somehow + const gpt4 = modelsRes.gpt4.map(r => JSON.parse(r)) + const gpt4turbo = modelsRes.gpt4turbo.map(r => JSON.parse(r)) - let modelName = 'gpt35turbo'; + let modelName = "gpt35turbo" for (const score of gpt35turbo.flatMap(({ scores }) => [...scores])) { - const [w1, w2] = score.words; - res[w1] = res[w1] || {}; - res[w1][w2] = res[w1][w2] || { human: {}, models: {} }; - res[w1][w2].models[modelName] = res[w1][w2].models[modelName] || { values: [] }; - res[w1][w2].models[modelName].values.push(score.score); + const [w1, w2] = score.words + res[w1] = res[w1] || {} + res[w1][w2] = res[w1][w2] || { human: {}, models: {} } + res[w1][w2].models[modelName] = res[w1][w2].models[modelName] || { + values: [], + } + res[w1][w2].models[modelName].values.push(score.score) } for (const w1 in res) { for (const w2 in res[w1]) { - res[w1][w2].models[modelName].avg = res[w1][w2] - .models[modelName] - .values - .reduce((a, b) => a + b, 0) / res[w1][w2].models[modelName].values.length; + res[w1][w2].models[modelName].avg = + res[w1][w2].models[modelName].values.reduce((a, b) => a + b, 0) / + res[w1][w2].models[modelName].values.length } } - modelName = 'gpt4'; + modelName = "gpt4" for (const score of gpt4.flatMap(({ scores }) => [...scores])) { - const [w1, w2] = score.words; - res[w1] = res[w1] || {}; - res[w1][w2] = res[w1][w2] || { human: {}, models: {} }; - res[w1][w2].models[modelName] = res[w1][w2].models[modelName] || { values: [] }; - res[w1][w2].models[modelName].values.push(score.score); + const [w1, w2] = score.words + res[w1] = res[w1] || {} + res[w1][w2] = res[w1][w2] || { human: {}, models: {} } + res[w1][w2].models[modelName] = res[w1][w2].models[modelName] || { + values: [], + } + res[w1][w2].models[modelName].values.push(score.score) } for (const w1 in res) { for (const w2 in res[w1]) { - res[w1][w2].models[modelName].avg = res[w1][w2] - .models[modelName] - .values - .reduce((a, b) => a + b, 0) / res[w1][w2].models[modelName].values.length; + res[w1][w2].models[modelName].avg = + res[w1][w2].models[modelName].values.reduce((a, b) => a + b, 0) / + res[w1][w2].models[modelName].values.length } } - modelName = 'gpt4turbo'; + modelName = "gpt4turbo" for (const score of gpt4turbo.flatMap(({ scores }) => [...scores])) { - const [w1, w2] = score.words; - res[w1] = res[w1] || {}; - res[w1][w2] = res[w1][w2] || { human: {}, models: {} }; - res[w1][w2].models[modelName] = res[w1][w2].models[modelName] || { values: [] }; - res[w1][w2].models[modelName].values.push(score.score); + const [w1, w2] = score.words + res[w1] = res[w1] || {} + res[w1][w2] = res[w1][w2] || { human: {}, models: {} } + res[w1][w2].models[modelName] = res[w1][w2].models[modelName] || { + values: [], + } + res[w1][w2].models[modelName].values.push(score.score) } for (const w1 in res) { for (const w2 in res[w1]) { - res[w1][w2].models[modelName].avg = res[w1][w2] - .models[modelName] - .values - .reduce((a, b) => a + b, 0) / res[w1][w2].models[modelName].values.length; + res[w1][w2].models[modelName].avg = + res[w1][w2].models[modelName].values.reduce((a, b) => a + b, 0) / + res[w1][w2].models[modelName].values.length } } for (const w1 in humanScores) { for (const w2 in humanScores[w1]) { - res[w1][w2].human = humanScores[w1][w2]; + res[w1][w2].human = humanScores[w1][w2] } } - return res; + return res } catch (e) { - throw new JsonSyntaxError(); + throw new JsonSyntaxError() } } @@ -314,7 +323,7 @@ const CompareMC30Experiment = { genPrompt, schema: resultSchema, runTrials, - validate + validate, } -export default CompareMC30Experiment; +export default CompareMC30Experiment diff --git a/src/lib/experiments/experiment.ts b/src/lib/experiments/experiment.ts index 0fb85c3..ad7b49c 100644 --- a/src/lib/experiments/experiment.ts +++ b/src/lib/experiments/experiment.ts @@ -1,55 +1,110 @@ -import OpenAI from "openai"; -import { Model } from "../models"; -import { DatasetProfile } from "../types"; -import { ValidationResult, ValidationType, combineValidations } from "../validation"; -import logger from "../logger"; -import fs from 'fs/promises'; -import oldFs from 'fs'; - +import OpenAI from "openai" +import { Model } from "../models" +import { DatasetProfile } from "../types" +import { + ValidationResult, + ValidationType, + combineValidations, +} from "../validation" +import logger from "../logger" +import fs from "fs/promises" +import oldFs from "fs" class Experiment { - name: string; - description: string; - genPrompt: (ds: DatasetProfile) => string; - schema: any; // TODO - runTrials: (this: Experiment, trials: number, ds: DatasetProfile, model: Model) => Promise; - validateTrial: (ds: DatasetProfile, data: string) => Promise; - validate: (ds: DatasetProfile, data: string[]) => Promise<{ trialResults: ValidationResult[], combinedResult: AggregatedValidationResult }>; - perform: (this: Experiment, trials: number, ds: DatasetProfile, model: Model, traceId?: number) => Promise; + name: string + description: string + genPrompt: (ds: DatasetProfile) => string + schema: any // TODO + runTrials: ( + this: Experiment, + trials: number, + ds: DatasetProfile, + model: Model, + ) => Promise + validateTrial: (ds: DatasetProfile, data: string) => Promise + validate: ( + ds: DatasetProfile, + data: string[], + ) => Promise<{ + trialResults: ValidationResult[] + combinedResult: AggregatedValidationResult + }> + perform: ( + this: Experiment, + trials: number, + ds: DatasetProfile, + model: Model, + traceId?: number, + ) => Promise constructor( name: string, description: string, genPrompt: (ds: DatasetProfile) => string, schema: any, - runTrial: (prompt: string, schema: any, ds: DatasetProfile, model: Model) => Promise, - validateTrial: (ds: DatasetProfile, data: string) => Promise, + runTrial: ( + prompt: string, + schema: any, + ds: DatasetProfile, + model: Model, + ) => Promise, + validateTrial: ( + ds: DatasetProfile, + data: string, + ) => Promise, ) { - this.name = name; - this.description = description; - this.genPrompt = genPrompt; - this.schema = schema; - this.runTrials = async function(this: Experiment, trials: number, ds: DatasetProfile, model: Model) { - const prompt = this.genPrompt(ds); - logger.info(`Running experiment ${this.name} ${trials} times on model ${model.modelId}.`); - logger.debug(`Prompt: ${prompt}`); - - const results = []; + this.name = name + this.description = description + this.genPrompt = genPrompt + this.schema = schema + this.runTrials = async function ( + this: Experiment, + trials: number, + ds: DatasetProfile, + model: Model, + ) { + const prompt = this.genPrompt(ds) + logger.info( + `Running experiment ${this.name} ${trials} times on model ${model.modelId}.`, + ) + logger.debug(`Prompt: ${prompt}`) + + const results = [] for (let i = 0; i < trials; i++) { logger.info(` trial #${i + 1} of ${trials}`) - const res = await runTrial(prompt, this.schema, ds, model); - results.push(res.type === 'openai' ? res.data.choices[0].message.tool_calls?.[0].function.arguments || '' : ''); + const res = await runTrial(prompt, this.schema, ds, model) + results.push( + res.type === "openai" + ? res.data.choices[0].message.tool_calls?.[0].function.arguments || + "" + : "", + ) + } + return results + } + this.validateTrial = validateTrial + this.validate = async function ( + this: Experiment, + ds: DatasetProfile, + data: string[], + ) { + const trialResults = await Promise.all( + data.map(d => this.validateTrial(ds, d)), + ) + return { + trialResults, + combinedResult: await combineValidations(trialResults), } - return results; } - this.validateTrial = validateTrial; - this.validate = async function(this: Experiment, ds: DatasetProfile, data: string[]) { - const trialResults = await Promise.all(data.map((d) => this.validateTrial(ds, d))); - return { trialResults, combinedResult: await combineValidations(trialResults) }; - }; - this.perform = async function(this: Experiment, trials: number, ds: DatasetProfile, model: Model, traceId?: number): Promise { - const results = await this.runTrials(trials, ds, model); - const { trialResults, combinedResult } = await this.validate(ds, results); + this.perform = async function ( + this: Experiment, + trials: number, + ds: DatasetProfile, + model: Model, + traceId?: number, + ): Promise { + const results = await this.runTrials(trials, ds, model) + const { trialResults, combinedResult } = await this.validate(ds, results) const expData = { name: this.name, @@ -59,56 +114,56 @@ class Experiment { dsId: ds.id, modelId: model.modelId, trialResults, - combinedResult - }; + combinedResult, + } - await saveExperimentData(expData); - return expData; + await saveExperimentData(expData) + return expData } } } export async function saveExperimentData(data: ExperimentData) { - const ts = data.traceId; - const dsId = data.dsId; - const expName = data.name; - const modelId = data.modelId; - const rootFolder = './results'; - const filename = `${rootFolder}/${ts}_${expName}_${dsId}_${modelId}.json`; - const json = JSON.stringify(data, null, 2); - - logger.info(`Saving experiment ${data.name} ${data.trialResults.length} times on model ${data.modelId} to ${filename}.`); + const ts = data.traceId + const dsId = data.dsId + const expName = data.name + const modelId = data.modelId + const rootFolder = "./results" + const filename = `${rootFolder}/${ts}_${expName}_${dsId}_${modelId}.json` + const json = JSON.stringify(data, null, 2) + + logger.info( + `Saving experiment ${data.name} ${data.trialResults.length} times on model ${data.modelId} to ${filename}.`, + ) if (!oldFs.existsSync(rootFolder)) { - await fs.mkdir(rootFolder); + await fs.mkdir(rootFolder) } - await fs.writeFile(filename, json); + await fs.writeFile(filename, json) } export interface ExperimentData { - name: string; - traceId: number; + name: string + traceId: number prompt: string - schema: any; - dsId: string; - modelId: string; - trialResults: ValidationResult[], - combinedResult: AggregatedValidationResult, + schema: any + dsId: string + modelId: string + trialResults: ValidationResult[] + combinedResult: AggregatedValidationResult } export interface AggregatedValidationResult { - avg: number; + avg: number resultTypes: { - [key in ValidationType]: number; + [key in ValidationType]: number } } export type TrialResult = { - type: 'openai'; - data: OpenAI.Chat.Completions.ChatCompletion; + type: "openai" + data: OpenAI.Chat.Completions.ChatCompletion } -export default Experiment; - - +export default Experiment diff --git a/src/lib/experiments/index.ts b/src/lib/experiments/index.ts index 0b82231..21c09c9 100644 --- a/src/lib/experiments/index.ts +++ b/src/lib/experiments/index.ts @@ -1,19 +1,16 @@ -import dsSampleFromDsName from "./prior-knowledge/dsSampleFromDsName"; -export { dsSampleFromDsName }; +import dsSampleFromDsName from "./prior-knowledge/dsSampleFromDsName" +export { dsSampleFromDsName } -import dsPaperFromDsName from "./prior-knowledge/dsPaperFromDsName"; -export { dsPaperFromDsName }; +import dsPaperFromDsName from "./prior-knowledge/dsPaperFromDsName" +export { dsPaperFromDsName } -import dsSampleFromDsSample from "./prior-knowledge/dsSampleFromDsSample"; -export { dsSampleFromDsSample }; - -import dsNameFromDsSample from "./prior-knowledge/dsNameFromDsSample"; -export { dsNameFromDsSample }; - -import compareMc30 from "./compare-mc30"; -export { compareMc30 }; - -export * from "./experiment"; +import dsSampleFromDsSample from "./prior-knowledge/dsSampleFromDsSample" +export { dsSampleFromDsSample } +import dsNameFromDsSample from "./prior-knowledge/dsNameFromDsSample" +export { dsNameFromDsSample } +import compareMc30 from "./compare-mc30" +export { compareMc30 } +export * from "./experiment" diff --git a/src/lib/experiments/prior-knowledge/dsNameFromDsSample.ts b/src/lib/experiments/prior-knowledge/dsNameFromDsSample.ts index 3f13c51..212533b 100644 --- a/src/lib/experiments/prior-knowledge/dsNameFromDsSample.ts +++ b/src/lib/experiments/prior-knowledge/dsNameFromDsSample.ts @@ -1,66 +1,81 @@ -import Experiment from "../experiment"; -import { Model } from "../../models"; -import { DatasetProfile } from "../../types"; -import { DataCorrect, DataIncomplete, DataIncorrect, DataPartiallyIncorrect, JsonSyntaxError, NoData, ValidationResult, ValidationType, combineValidations } from "../../validation"; +import Experiment from "../experiment" +import { Model } from "../../models" +import { DatasetProfile } from "../../types" +import { + DataCorrect, + DataIncomplete, + DataIncorrect, + DataPartiallyIncorrect, + JsonSyntaxError, + NoData, + ValidationResult, + ValidationType, + combineValidations, +} from "../../validation" - -const name = 'ds-name-from-ds-sample'; -const description = 'Check if LLM knows a dataset by giving it 10 pairs and asking for 5 more.'; +const name = "ds-name-from-ds-sample" +const description = + "Check if LLM knows a dataset by giving it 10 pairs and asking for 5 more." const genPrompt = (ds: DatasetProfile) => { - return `Which semantic measures evaluation dataset do these pairs of concepts belong to?\n` + - ds.partitions[0].data.slice(0, 10).map(({ word1, word2 }) => `${word1} ${word2}`).join('\n'); + return ( + `Which semantic measures evaluation dataset do these pairs of concepts belong to?\n` + + ds.partitions[0].data + .slice(0, 10) + .map(({ word1, word2 }) => `${word1} ${word2}`) + .join("\n") + ) } const resultSchema = { - "type": "object", - "properties": { - "name": { - "type": "string", + type: "object", + properties: { + name: { + type: "string", }, - "year": { - "type": "string", + year: { + type: "string", }, - "authors": { - "type": "array", - "items": { - type: 'string' - } - } - } + authors: { + type: "array", + items: { + type: "string", + }, + }, + }, } -async function runTrial(prompt: string, schema: any, _: DatasetProfile, model: Model) { +async function runTrial( + prompt: string, + schema: any, + _: DatasetProfile, + model: Model, +) { const f = { - name: 'validate_dataset', - description: 'Validates the dataset information.', - parameters: schema - }; + name: "validate_dataset", + description: "Validates the dataset information.", + parameters: schema, + } - const result = await model.makeRequest(prompt, { function: f }); - return result; + const result = await model.makeRequest(prompt, { function: f }) + return result } - async function validateTrial(ds: DatasetProfile, data: string) { - if (!data.trim()) { return new NoData(); } + if (!data.trim()) { + return new NoData() + } try { - const got = JSON.parse(data); - return new DataCorrect(got); + const got = JSON.parse(data) + return new DataCorrect(got) } catch (e) { - return new JsonSyntaxError(data); + return new JsonSyntaxError(data) } } - - - export default new Experiment( name, description, genPrompt, resultSchema, runTrial, - validateTrial -); - - - + validateTrial, +) diff --git a/src/lib/experiments/prior-knowledge/dsPaperFromDsName.ts b/src/lib/experiments/prior-knowledge/dsPaperFromDsName.ts index a6be6a2..5c3c8ba 100644 --- a/src/lib/experiments/prior-knowledge/dsPaperFromDsName.ts +++ b/src/lib/experiments/prior-knowledge/dsPaperFromDsName.ts @@ -1,71 +1,89 @@ -import Experiment, { TrialResult } from "../experiment"; -import { Model } from "../../models"; -import { DatasetProfile } from "../../types"; -import { DataCorrect, DataIncomplete, DataIncorrect, DataPartiallyIncorrect, JsonSchemaError, JsonSyntaxError, NoData } from "../../validation"; -import { distance } from 'fastest-levenshtein'; +import Experiment, { TrialResult } from "../experiment" +import { Model } from "../../models" +import { DatasetProfile } from "../../types" +import { + DataCorrect, + DataIncomplete, + DataIncorrect, + DataPartiallyIncorrect, + JsonSchemaError, + JsonSyntaxError, + NoData, +} from "../../validation" +import { distance } from "fastest-levenshtein" import Ajv, { JSONSchemaType } from "ajv" const ajv = new Ajv() - -const name = 'ds-paper-from-ds-name'; -const description = 'Check if LLM can, when given a dataset name, identify the scientific paper describing it'; +const name = "ds-paper-from-ds-name" +const description = + "Check if LLM can, when given a dataset name, identify the scientific paper describing it" const genPrompt = (ds: DatasetProfile) => { - const year = ds.metadata.date.split('-')[0]; + const year = ds.metadata.date.split("-")[0] return `${ds.metadata.name} is a semantic measure gold standard dataset, published in ${year}. Please return the title of the scientific article describing this dataset.` } const resultSchema = { - "type": "object", - "properties": { - "title": { - "type": "string", - } - } + type: "object", + properties: { + title: { + type: "string", + }, + }, } -type ResultSchema = JSONSchemaType; +type ResultSchema = JSONSchemaType -const validateSchema = ajv.compile(resultSchema); +const validateSchema = ajv.compile(resultSchema) -async function runTrial(prompt: string, schema: any, _: DatasetProfile, model: Model) { +async function runTrial( + prompt: string, + schema: any, + _: DatasetProfile, + model: Model, +) { const f = { - name: 'return-paper-name', - description: 'Return the title of the scientific article describing this dataset', - parameters: schema + name: "return-paper-name", + description: + "Return the title of the scientific article describing this dataset", + parameters: schema, } - const result = await model.makeRequest(prompt, { function: f }); - return result; + const result = await model.makeRequest(prompt, { function: f }) + return result } - async function validateTrial(ds: DatasetProfile, data: string) { - if (!data.trim()) { return new NoData(); } + if (!data.trim()) { + return new NoData() + } try { - const got = JSON.parse(data); + const got = JSON.parse(data) if (!validateSchema(got)) { - return new JsonSchemaError(data); + return new JsonSchemaError(data) } - const expected = ds.metadata.papers.map(p => ({ title: p.title })); + const expected = ds.metadata.papers.map(p => ({ title: p.title })) - let bestScore = 1; - let bestIndex = -1; + let bestScore = 1 + let bestIndex = -1 for (const [i, exp] of expected.entries()) { - const e = exp.title.toLowerCase().trim(); - const g = got.title.toLowerCase().trim(); - const d = distance(e, g) / ((e.length + g.length) / 2); + const e = exp.title.toLowerCase().trim() + const g = got.title.toLowerCase().trim() + const d = distance(e, g) / ((e.length + g.length) / 2) if (d < bestScore) { - bestScore = d; - bestIndex = i; + bestScore = d + bestIndex = i } } - const threshold = 0.2; + const threshold = 0.2 if (bestScore < threshold) { - return new DataCorrect(got.title); + return new DataCorrect(got.title) } - return new DataIncorrect({ got: got.title, expected: expected.map(e => e.title) }); + return new DataIncorrect({ + got: got.title, + expected: expected.map(e => e.title), + }) } catch (e) { - return new JsonSyntaxError(data); + return new JsonSyntaxError(data) } } @@ -75,8 +93,5 @@ export default new Experiment( genPrompt, resultSchema, runTrial, - validateTrial -); - - - + validateTrial, +) diff --git a/src/lib/experiments/prior-knowledge/dsSampleFromDsName.test.ts b/src/lib/experiments/prior-knowledge/dsSampleFromDsName.test.ts index cfcf1c2..1055c84 100644 --- a/src/lib/experiments/prior-knowledge/dsSampleFromDsName.test.ts +++ b/src/lib/experiments/prior-knowledge/dsSampleFromDsName.test.ts @@ -1,151 +1,160 @@ - -import { describe, expect, test } from '@jest/globals'; -import dsSampleFromDsName from './dsSampleFromDsName'; -import { Model } from '../../models/model'; -import { DatasetProfile } from '../../types'; +import { describe, expect, test } from "@jest/globals" +import dsSampleFromDsName from "./dsSampleFromDsName" +import { Model } from "../../models/model" +import { DatasetProfile } from "../../types" const createMockDataset = () => ({ - id: 'test', + id: "test", metadata: { - name: 'Dataset Name', - description: 'test', + name: "Dataset Name", + description: "test", papers: [], urls: [], - date: '2021-01-01', + date: "2021-01-01", downloadUrls: [], measureTypes: [], }, partitions: [ { - id: 'test', - measureType: 'similarity' as const, + id: "test", + measureType: "similarity" as const, data: [ { - word1: 'test', - word2: 'test', + word1: "test", + word2: "test", value: 0.5, values: [0.5], }, ], }, ], -}); - -const createMockModel = (result: string) => new Model('test', jest.fn(() => Promise.resolve({ - type: 'openai', data: { - id: 'test', - model: 'test', - object: 'chat.completion', - created: 0, - choices: [{ - finish_reason: 'function_call', - index: 0, - message: { - content: null, - role: 'assistant', - tool_calls: [{ - id: 'test', - type: 'function', - function: { - name: 'test', - arguments: result - } - }] - } - }] - } -}))); - - -describe('dsSampleFromDsName', () => { - describe('genPrompt', () => { - test('should generate a prompt', () => { - const ds: DatasetProfile = createMockDataset(); - - const prompt = dsSampleFromDsName.genPrompt(ds); - expect(prompt).toEqual(expect.stringContaining('Dataset Name')); - expect(prompt).toEqual(expect.stringContaining('2021')); - }); - }); - - describe('run', () => { - test('should call model.makeRequest', async () => { - const ds: DatasetProfile = createMockDataset(); - - const model = createMockModel('this is the result'); - - await dsSampleFromDsName.runTrials(2, ds, model); - expect(model.makeRequest).toHaveBeenCalledTimes(2); - }); - - test('should return model.makeRequest result', async () => { - const ds: DatasetProfile = createMockDataset(); - - const model = createMockModel('this is the result'); - - const result = await dsSampleFromDsName.runTrials(2, ds, model); - expect(result.length).toEqual(2); - expect(result[0]).toEqual('this is the result'); - expect(result[1]).toEqual('this is the result'); - }); - - - test('should return empty string if model.makeRequest returns no data', async () => { - const ds: DatasetProfile = createMockDataset(); - - const model = createMockModel(''); - - const result = await dsSampleFromDsName.runTrials(1, ds, model); - expect(model.makeRequest).toHaveBeenCalled(); - expect(result.length).toEqual(1); - expect(result[0]).toEqual(''); - }); - - }); - - describe('validateTrial', () => { - test('should return NoData if data is empty', async () => { - const ds: DatasetProfile = createMockDataset(); - - const result = await dsSampleFromDsName.validateTrial(ds, ''); - expect(result.type).toEqual('no-data'); - }); - - test('should return DataIncorrect if data is incorrect', async () => { - const ds: DatasetProfile = createMockDataset(); - - const result = await dsSampleFromDsName.validateTrial(ds, +}) + +const createMockModel = (result: string) => + new Model( + "test", + jest.fn(() => + Promise.resolve({ + type: "openai", + data: { + id: "test", + model: "test", + object: "chat.completion", + created: 0, + choices: [ + { + finish_reason: "function_call", + index: 0, + message: { + content: null, + role: "assistant", + tool_calls: [ + { + id: "test", + type: "function", + function: { + name: "test", + arguments: result, + }, + }, + ], + }, + }, + ], + }, + }), + ), + ) + +describe("dsSampleFromDsName", () => { + describe("genPrompt", () => { + test("should generate a prompt", () => { + const ds: DatasetProfile = createMockDataset() + + const prompt = dsSampleFromDsName.genPrompt(ds) + expect(prompt).toEqual(expect.stringContaining("Dataset Name")) + expect(prompt).toEqual(expect.stringContaining("2021")) + }) + }) + + describe("run", () => { + test("should call model.makeRequest", async () => { + const ds: DatasetProfile = createMockDataset() + + const model = createMockModel("this is the result") + + await dsSampleFromDsName.runTrials(2, ds, model) + expect(model.makeRequest).toHaveBeenCalledTimes(2) + }) + + test("should return model.makeRequest result", async () => { + const ds: DatasetProfile = createMockDataset() + + const model = createMockModel("this is the result") + + const result = await dsSampleFromDsName.runTrials(2, ds, model) + expect(result.length).toEqual(2) + expect(result[0]).toEqual("this is the result") + expect(result[1]).toEqual("this is the result") + }) + + test("should return empty string if model.makeRequest returns no data", async () => { + const ds: DatasetProfile = createMockDataset() + + const model = createMockModel("") + + const result = await dsSampleFromDsName.runTrials(1, ds, model) + expect(model.makeRequest).toHaveBeenCalled() + expect(result.length).toEqual(1) + expect(result[0]).toEqual("") + }) + }) + + describe("validateTrial", () => { + test("should return NoData if data is empty", async () => { + const ds: DatasetProfile = createMockDataset() + + const result = await dsSampleFromDsName.validateTrial(ds, "") + expect(result.type).toEqual("no-data") + }) + + test("should return DataIncorrect if data is incorrect", async () => { + const ds: DatasetProfile = createMockDataset() + + const result = await dsSampleFromDsName.validateTrial( + ds, JSON.stringify({ - pairs: [ - ['test', 'test2'], - ] - }) - ); - expect(result.type).toEqual('data-incorrect'); - }); + pairs: [["test", "test2"]], + }), + ) + expect(result.type).toEqual("data-incorrect") + }) - test('should return DataPartiallyIncorrect if data is partially incorrect', async () => { - const ds: DatasetProfile = createMockDataset(); + test("should return DataPartiallyIncorrect if data is partially incorrect", async () => { + const ds: DatasetProfile = createMockDataset() - const result = await dsSampleFromDsName.validateTrial(ds, + const result = await dsSampleFromDsName.validateTrial( + ds, JSON.stringify({ pairs: [ - ['test', 'test2'], - ['test', 'test'], - ] - }) - ); - expect(result.type).toEqual('data-partially-incorrect'); - }); - - test('should return JsonSyntaxError if data is not valid JSON', async () => { - const ds: DatasetProfile = createMockDataset(); - - const result = await dsSampleFromDsName.validateTrial(ds, 'not valid json'); - expect(result.type).toEqual('json-syntax-error'); - }); - }); -}); - + ["test", "test2"], + ["test", "test"], + ], + }), + ) + expect(result.type).toEqual("data-partially-incorrect") + }) + + test("should return JsonSyntaxError if data is not valid JSON", async () => { + const ds: DatasetProfile = createMockDataset() + + const result = await dsSampleFromDsName.validateTrial( + ds, + "not valid json", + ) + expect(result.type).toEqual("json-syntax-error") + }) + }) +}) diff --git a/src/lib/experiments/prior-knowledge/dsSampleFromDsName.ts b/src/lib/experiments/prior-knowledge/dsSampleFromDsName.ts index 8c275d9..9ccc1c1 100644 --- a/src/lib/experiments/prior-knowledge/dsSampleFromDsName.ts +++ b/src/lib/experiments/prior-knowledge/dsSampleFromDsName.ts @@ -1,90 +1,103 @@ -import Experiment, { TrialResult } from "../experiment"; -import { Model } from "../../models"; -import { DatasetProfile } from "../../types"; -import { DataCorrect, DataIncomplete, DataIncorrect, DataPartiallyIncorrect, JsonSyntaxError, NoData } from "../../validation"; - - -const name = 'ds-sample-from-ds-name'; -const description = 'Check if LLM knows a dataset by asking it to list 5 pairs included in the dataset'; +import Experiment, { TrialResult } from "../experiment" +import { Model } from "../../models" +import { DatasetProfile } from "../../types" +import { + DataCorrect, + DataIncomplete, + DataIncorrect, + DataPartiallyIncorrect, + JsonSyntaxError, + NoData, +} from "../../validation" + +const name = "ds-sample-from-ds-name" +const description = + "Check if LLM knows a dataset by asking it to list 5 pairs included in the dataset" const genPrompt = (ds: DatasetProfile) => { - const year = ds.metadata.date.split('-')[0]; - const measureTypes = ds.metadata.measureTypes.join(' and '); - return `${ds.metadata.name} is a semantic measure gold standard dataset, published in ${year}. ` + + const year = ds.metadata.date.split("-")[0] + const measureTypes = ds.metadata.measureTypes.join(" and ") + return ( + `${ds.metadata.name} is a semantic measure gold standard dataset, published in ${year}. ` + `It is composed of pairs of concepts and their semantic ${measureTypes} score as reported by humans. ` + `Please list 5 pairs of concepts sampled from this dataset.` + ) } const resultSchema = { - "type": "object", - "properties": { - "pairs": { - "type": "array", - "items": { - "type": "array", + type: "object", + properties: { + pairs: { + type: "array", + items: { + type: "array", items: { - type: 'string' - } - } - } - } + type: "string", + }, + }, + }, + }, } -async function runTrial(prompt: string, schema: any, _: DatasetProfile, model: Model) { +async function runTrial( + prompt: string, + schema: any, + _: DatasetProfile, + model: Model, +) { const f = { - name: 'validate_sample', - description: 'Validates the pairs sampled from the dataset.', - parameters: schema - }; + name: "validate_sample", + description: "Validates the pairs sampled from the dataset.", + parameters: schema, + } - const result = await model.makeRequest(prompt, { function: f }); - return result; + const result = await model.makeRequest(prompt, { function: f }) + return result } - async function validateTrial(ds: DatasetProfile, data: string) { - if (!data.trim()) { return new NoData(); } + if (!data.trim()) { + return new NoData() + } try { - const got = JSON.parse(data); - const expected: { [word: string]: { [word: string]: boolean } } = {}; + const got = JSON.parse(data) + const expected: { [word: string]: { [word: string]: boolean } } = {} for (let { word1, word2 } of ds.partitions[0].data) { - const w1 = word1.toLowerCase(); - const w2 = word2.toLowerCase(); + const w1 = word1.toLowerCase() + const w2 = word2.toLowerCase() - expected[w1] = expected[w1] || {}; - expected[w1][w2] = true; - expected[w2] = expected[w2] || {}; - expected[w2][w1] = true; + expected[w1] = expected[w1] || {} + expected[w1][w2] = true + expected[w2] = expected[w2] || {} + expected[w2][w1] = true } - let i = 0; - let dataIncorrect = false; + let i = 0 + let dataIncorrect = false for (let [word1, word2] of got.pairs) { - const w1 = word1.toLowerCase(); - const w2 = word2.toLowerCase(); + const w1 = word1.toLowerCase() + const w2 = word2.toLowerCase() if (expected[w1]?.[w2] || expected[w2]?.[w1]) { - i++; - expected[w1][w2] = false; - expected[w2][w1] = false; + i++ + expected[w1][w2] = false + expected[w2][w1] = false } else { - dataIncorrect = true; + dataIncorrect = true } } if (i === 0) { - return new DataIncorrect(got); + return new DataIncorrect(got) } if (dataIncorrect) { - return new DataPartiallyIncorrect(i / 5, got); + return new DataPartiallyIncorrect(i / 5, got) } if (i < 5) { - return new DataIncomplete(i / 5, got); + return new DataIncomplete(i / 5, got) } - return new DataCorrect(got); - + return new DataCorrect(got) } catch (e) { - return new JsonSyntaxError(data); + return new JsonSyntaxError(data) } - } export default new Experiment( @@ -93,8 +106,5 @@ export default new Experiment( genPrompt, resultSchema, runTrial, - validateTrial -); - - - + validateTrial, +) diff --git a/src/lib/experiments/prior-knowledge/dsSampleFromDsSample.ts b/src/lib/experiments/prior-knowledge/dsSampleFromDsSample.ts index 9bf53c3..689520c 100644 --- a/src/lib/experiments/prior-knowledge/dsSampleFromDsSample.ts +++ b/src/lib/experiments/prior-knowledge/dsSampleFromDsSample.ts @@ -1,90 +1,106 @@ -import Experiment, { TrialResult } from "../experiment"; -import { Model } from "../../models"; -import { DatasetProfile } from "../../types"; -import { DataCorrect, DataIncomplete, DataIncorrect, DataPartiallyIncorrect, JsonSyntaxError, NoData } from "../../validation"; - - -const name = 'ds-sample-from-ds-sample'; -const description = 'Check if LLM knows a dataset by giving it 10 pairs and asking for 5 more.'; +import Experiment, { TrialResult } from "../experiment" +import { Model } from "../../models" +import { DatasetProfile } from "../../types" +import { + DataCorrect, + DataIncomplete, + DataIncorrect, + DataPartiallyIncorrect, + JsonSyntaxError, + NoData, +} from "../../validation" + +const name = "ds-sample-from-ds-sample" +const description = + "Check if LLM knows a dataset by giving it 10 pairs and asking for 5 more." const genPrompt = (ds: DatasetProfile) => { - const numberOfPairs = ds.partitions.reduce((acc, p) => acc + p.data.length, 0); - const measureTypes = ds.metadata.measureTypes.join(' and '); - return `A published semantic measure gold standard dataset is composed of ${numberOfPairs} pairs of concepts and their semantic ${measureTypes} score as reported by humans. ` + + const numberOfPairs = ds.partitions.reduce((acc, p) => acc + p.data.length, 0) + const measureTypes = ds.metadata.measureTypes.join(" and ") + return ( + `A published semantic measure gold standard dataset is composed of ${numberOfPairs} pairs of concepts and their semantic ${measureTypes} score as reported by humans. ` + `I only have 10 of the pairs included in the dataset. Please give me a list of 5 other pairs of concepts belonging to the same dataset but not included in my list.\n` + - ds.partitions[0].data.slice(0, 10).map(({ word1, word2 }) => `${word1} ${word2}`).join('\n'); + ds.partitions[0].data + .slice(0, 10) + .map(({ word1, word2 }) => `${word1} ${word2}`) + .join("\n") + ) } const resultSchema = { - "type": "object", - "properties": { - "pairs": { - "type": "array", - "items": { - "type": "array", + type: "object", + properties: { + pairs: { + type: "array", + items: { + type: "array", items: { - type: 'string' - } - } - } - } + type: "string", + }, + }, + }, + }, } -async function runTrial(prompt: string, schema: any, _: DatasetProfile, model: Model) { +async function runTrial( + prompt: string, + schema: any, + _: DatasetProfile, + model: Model, +) { const f = { - name: 'validate_sample', - description: 'Validates the pairs sampled from the dataset.', - parameters: schema - }; + name: "validate_sample", + description: "Validates the pairs sampled from the dataset.", + parameters: schema, + } - const result = await model.makeRequest(prompt, { function: f }); - return result; + const result = await model.makeRequest(prompt, { function: f }) + return result } - async function validateTrial(ds: DatasetProfile, data: string) { - if (!data.trim()) { return new NoData(); } + if (!data.trim()) { + return new NoData() + } try { - const got = JSON.parse(data); - const expected: { [word: string]: { [word: string]: boolean } } = {}; + const got = JSON.parse(data) + const expected: { [word: string]: { [word: string]: boolean } } = {} for (let { word1, word2 } of ds.partitions[0].data) { - const w1 = word1.toLowerCase(); - const w2 = word2.toLowerCase(); + const w1 = word1.toLowerCase() + const w2 = word2.toLowerCase() - expected[w1] = expected[w1] || {}; - expected[w1][w2] = true; - expected[w2] = expected[w2] || {}; - expected[w2][w1] = true; + expected[w1] = expected[w1] || {} + expected[w1][w2] = true + expected[w2] = expected[w2] || {} + expected[w2][w1] = true } - let i = 0; - let dataIncorrect = false; + let i = 0 + let dataIncorrect = false for (let [word1, word2] of got.pairs) { - const w1 = word1.toLowerCase(); - const w2 = word2.toLowerCase(); + const w1 = word1.toLowerCase() + const w2 = word2.toLowerCase() if (expected[w1]?.[w2] || expected[w2]?.[w1]) { - i++; - expected[w1][w2] = false; - expected[w2][w1] = false; + i++ + expected[w1][w2] = false + expected[w2][w1] = false } else { - dataIncorrect = true; + dataIncorrect = true } } if (i === 0) { - return new DataIncorrect(got); + return new DataIncorrect(got) } if (dataIncorrect) { - return new DataPartiallyIncorrect(i / 5, got); + return new DataPartiallyIncorrect(i / 5, got) } if (i < 5) { - return new DataIncomplete(i / 5, got); + return new DataIncomplete(i / 5, got) } - return new DataCorrect(got); - + return new DataCorrect(got) } catch (e) { - return new JsonSyntaxError(data); + return new JsonSyntaxError(data) } - } export default new Experiment( @@ -93,8 +109,5 @@ export default new Experiment( genPrompt, resultSchema, runTrial, - validateTrial -); - - - + validateTrial, +) diff --git a/src/lib/logger.ts b/src/lib/logger.ts index ecd0afb..3e9ee94 100644 --- a/src/lib/logger.ts +++ b/src/lib/logger.ts @@ -1,24 +1,25 @@ -import pino from 'pino'; +import pino from "pino" -const level = process.env.PINO_LOG_LEVEL || 'info'; +const level = process.env.PINO_LOG_LEVEL || "info" const transport = pino.transport({ targets: [ { level, - target: 'pino/file', + target: "pino/file", options: { destination: `${__dirname}/../../app.log` }, }, { level, - target: 'pino-pretty', + target: "pino-pretty", }, ], -}); +}) -export default pino({ - level, - timestamp: pino.stdTimeFunctions.isoTime, -}, - transport -); +export default pino( + { + level, + timestamp: pino.stdTimeFunctions.isoTime, + }, + transport, +) diff --git a/src/lib/models/index.ts b/src/lib/models/index.ts index dd5144f..145ddce 100644 --- a/src/lib/models/index.ts +++ b/src/lib/models/index.ts @@ -1,5 +1,4 @@ -export * from './model'; -export * from "./openai"; +export * from "./model" +export * from "./openai" - -export type ModelIds = 'gpt35turbo' | 'gpt4' | 'gpt4turbo'; +export type ModelIds = "gpt35turbo" | "gpt4" | "gpt4turbo" diff --git a/src/lib/models/model.ts b/src/lib/models/model.ts index 57dd58d..324e81e 100644 --- a/src/lib/models/model.ts +++ b/src/lib/models/model.ts @@ -1,18 +1,17 @@ -import { OpenAIModelParams } from "./openai"; -import { TrialResult } from "../experiments"; +import { OpenAIModelParams } from "./openai" +import { TrialResult } from "../experiments" export class Model { - modelId: string; - makeRequest: (prompt: string, params: ModelParams) => Promise; + modelId: string + makeRequest: (prompt: string, params: ModelParams) => Promise constructor( modelId: string, - makeRequest: (prompt: string, params: ModelParams) => Promise + makeRequest: (prompt: string, params: ModelParams) => Promise, ) { - this.modelId = modelId; - this.makeRequest = makeRequest; + this.modelId = modelId + this.makeRequest = makeRequest } } -export type ModelParams = OpenAIModelParams; - +export type ModelParams = OpenAIModelParams diff --git a/src/lib/models/openai.ts b/src/lib/models/openai.ts index 2d3ffc4..e295fd7 100644 --- a/src/lib/models/openai.ts +++ b/src/lib/models/openai.ts @@ -1,56 +1,60 @@ -import OpenAI from "openai"; -import { Model } from "./model"; -import logger from "../logger"; -import 'dotenv/config'; +import OpenAI from "openai" +import { Model } from "./model" +import logger from "../logger" +import "dotenv/config" const configuration = { apiKey: process.env.OPENAI_API_KEY, -}; - +} export interface OpenAIModelParams { function: OpenAI.Chat.Completions.ChatCompletionCreateParams.Function } if (!configuration.apiKey) { - logger.error("OpenAI API key not configured, please follow instructions in README.md"); + logger.error( + "OpenAI API key not configured, please follow instructions in README.md", + ) } else { - logger.info("OpenAI API key loaded from environment variable"); + logger.info("OpenAI API key loaded from environment variable") } -const openai = new OpenAI(configuration); - +const openai = new OpenAI(configuration) const buildModel = (openai: OpenAI, modelId: string) => { - const makeRequest = async function(prompt: string, params: OpenAIModelParams) { + const makeRequest = async function ( + prompt: string, + params: OpenAIModelParams, + ) { const completion = await openai.chat.completions.create({ model: modelId, messages: [ { role: "system", content: "You are a helpful recipe assistant." }, { - role: 'user', + role: "user", content: prompt, - - } + }, + ], + tools: [ + { + type: "function", + // omitting description seems to yield better results + function: { + name: params.function.name, + parameters: params.function.parameters, + }, + }, ], - tools: [{ - type: 'function', - // omitting description seems to yield better results - function: { - name: params.function.name, - parameters: params.function.parameters - } - }], tool_choice: { - type: 'function', - function: { name: params.function.name } + type: "function", + function: { name: params.function.name }, }, - }); - return { type: 'openai' as const, data: completion }; - }; + }) + return { type: "openai" as const, data: completion } + } - return new Model(modelId, makeRequest); + return new Model(modelId, makeRequest) } -export const gpt35turbo = buildModel(openai, "gpt-3.5-turbo-1106"); -export const gpt4 = buildModel(openai, "gpt-4-0613"); -export const gpt4turbo = buildModel(openai, "gpt-4-1106-preview"); +export const gpt35turbo = buildModel(openai, "gpt-3.5-turbo-1106") +export const gpt4 = buildModel(openai, "gpt-4-0613") +export const gpt4turbo = buildModel(openai, "gpt-4-1106-preview") diff --git a/src/lib/types.ts b/src/lib/types.ts index 098dfd6..a9fcc98 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,94 +1,92 @@ - export interface DatasetProfile { /** * An identifier for the dataset */ - id: string, + id: string /** * Metadata for the dataset */ - metadata: Metadata, + metadata: Metadata /** * The original instructions given to the annotators */ - originalInstructions?: string, + originalInstructions?: string /** * The partitions containing the dataset data */ - partitions: Partition[], + partitions: Partition[] } interface Metadata { /** * The name of the dataset */ - name: string; + name: string /** * Web sites containing information about the dataset * * @items {"type": "string", "format": "uri"} */ - urls: string[], + urls: string[] /** * Information about the scientific papers describing the dataset */ - papers: Paper[], + papers: Paper[] /** * The date the dataset was published * * @TJS-pattern ^[0-9]{4}(-[0-9]{2}(-[0-9]{2})?)?$ */ - date: string, + date: string /** * A description of the dataset */ - description: string, + description: string /** * URL(s) to download the dataset files * - * @items {"type": "string", "format": "uri"} + * @items {"type": "string", "format": "uri"} */ - downloadUrls: string[], + downloadUrls: string[] /** * Which type of measures are used to compare the words */ - measureTypes: ('similarity' | 'relatedness')[], + measureTypes: ("similarity" | "relatedness")[] } - export interface Paper { /** * The title of the paper */ - title: string, + title: string /** * The URL where the paper can be found * * @format uri */ - url?: string, + url?: string } interface Partition { /** * An identifier for the partition */ - id: string, + id: string /** * Which type of measure is used to compare the words */ - measureType: 'similarity' | 'relatedness', + measureType: "similarity" | "relatedness" /** * The data for the partition */ @@ -99,21 +97,20 @@ type PartitionData = { /** * The first word in the pair */ - word1: string, + word1: string /** * The second word in the pair */ - word2: string, + word2: string } & ( - { + | { /** * The averaged numeric value of the semantic measure for the pair */ value: number - } | - { - + } + | { /** * The individual numeric values of the semantic measure for the pair * @@ -121,4 +118,4 @@ type PartitionData = { */ values: number[] } - ) +) diff --git a/src/lib/validation/index.ts b/src/lib/validation/index.ts index 0901c0e..a0eb737 100644 --- a/src/lib/validation/index.ts +++ b/src/lib/validation/index.ts @@ -1,84 +1,90 @@ -import { AggregatedValidationResult } from "../experiments"; +import { AggregatedValidationResult } from "../experiments" -export type ValidationType = 'json-syntax-error' | 'json-schema-error' | 'data-incomplete' | 'data-partially-incorrect' | 'data-incorrect' | 'no-data' | 'data-correct'; +export type ValidationType = + | "json-syntax-error" + | "json-schema-error" + | "data-incomplete" + | "data-partially-incorrect" + | "data-incorrect" + | "no-data" + | "data-correct" export class ValidationResult { - type: ValidationType; - ok: boolean; - data: any; + type: ValidationType + ok: boolean + data: any constructor(type: ValidationType, ok: boolean, data: any) { - this.type = type; - this.ok = ok; - this.data = data; + this.type = type + this.ok = ok + this.data = data } } - export class JsonSyntaxError extends ValidationResult { constructor(data?: any) { - super('json-syntax-error', false, data); + super("json-syntax-error", false, data) } } export class JsonSchemaError extends ValidationResult { constructor(data?: any) { - super('json-schema-error', false, data); + super("json-schema-error", false, data) } } export class DataIncomplete extends ValidationResult { - percentage: number; + percentage: number constructor(percentage: number, data?: any) { - super('data-incomplete', false, data); - this.percentage = percentage; + super("data-incomplete", false, data) + this.percentage = percentage } } export class DataPartiallyIncorrect extends ValidationResult { - percentage: number; + percentage: number constructor(percentage: number, data?: any) { - super('data-partially-incorrect', false, data); - this.percentage = percentage; + super("data-partially-incorrect", false, data) + this.percentage = percentage } } export class DataIncorrect extends ValidationResult { constructor(data?: any) { - super('data-incorrect', false, data); + super("data-incorrect", false, data) } } export class NoData extends ValidationResult { constructor() { - super('no-data', false, ''); + super("no-data", false, "") } } - export class DataCorrect extends ValidationResult { constructor(data?: any) { - super('data-correct', true, data); + super("data-correct", true, data) } } - -export async function combineValidations(vs: ValidationResult[]): Promise { - let sum = 0; - const resultTypes = {} as { [key in ValidationType]: number }; +export async function combineValidations( + vs: ValidationResult[], +): Promise { + let sum = 0 + const resultTypes = {} as { [key in ValidationType]: number } for (const v of vs) { - resultTypes[v.type] = resultTypes[v.type] || 0; - resultTypes[v.type]++; - if (v.type === 'data-correct') { - sum += 1; + resultTypes[v.type] = resultTypes[v.type] || 0 + resultTypes[v.type]++ + if (v.type === "data-correct") { + sum += 1 } - if ('percentage' in v && typeof v.percentage === 'number') { - sum += v.percentage; + if ("percentage" in v && typeof v.percentage === "number") { + sum += v.percentage } } - return { avg: sum / vs.length, resultTypes }; + return { avg: sum / vs.length, resultTypes } } diff --git a/src/scripts/compareMC30.ts b/src/scripts/compareMC30.ts index 44ead91..92a1f68 100644 --- a/src/scripts/compareMC30.ts +++ b/src/scripts/compareMC30.ts @@ -1,19 +1,19 @@ -import { compareMc30 } from "../lib/experiments"; -import { loadDatasetScores } from "../lib/experiments/compare-mc30"; -import logger from "../lib/logger"; +import { compareMc30 } from "../lib/experiments" +import { loadDatasetScores } from "../lib/experiments/compare-mc30" +import logger from "../lib/logger" -const trials = process.argv[2] ? parseInt(process.argv[2]) : 1; +const trials = process.argv[2] ? parseInt(process.argv[2]) : 1 const compareMC30 = async () => { - logger.info('Starting') - const res = await compareMc30.runTrials(trials); + logger.info("Starting") + const res = await compareMc30.runTrials(trials) - const humanScores = await loadDatasetScores(); + const humanScores = await loadDatasetScores() - await compareMc30.validate(res, humanScores); + await compareMc30.validate(res, humanScores) } compareMC30().then(() => { - logger.info('Done'); - process.exit(0); -}); + logger.info("Done") + process.exit(0) +}) diff --git a/src/scripts/dsNameFromDsSample.ts b/src/scripts/dsNameFromDsSample.ts index eeaa3e2..3d9dd1f 100644 --- a/src/scripts/dsNameFromDsSample.ts +++ b/src/scripts/dsNameFromDsSample.ts @@ -1,27 +1,43 @@ -import { DatasetProfile } from "punuy-datasets/src/lib/types"; -import logger from "../lib/logger"; -import { dsNameFromDsSample } from "../lib/experiments"; -import { gpt35turbo, gpt4, gpt4turbo } from "../lib/models"; -import { rg65 } from "punuy-datasets"; +import { DatasetProfile } from "punuy-datasets/src/lib/types" +import logger from "../lib/logger" +import { dsNameFromDsSample } from "../lib/experiments" +import { gpt35turbo, gpt4, gpt4turbo } from "../lib/models" +import { rg65 } from "punuy-datasets" -const trials = process.argv[2] ? parseInt(process.argv[2]) : 3; +const trials = process.argv[2] ? parseInt(process.argv[2]) : 3 const nameFromSample = async (ds: DatasetProfile) => { - logger.info('Starting') - const timestamp = Date.now(); - const gpt35turbo_res = await dsNameFromDsSample.perform(trials, ds, gpt35turbo, timestamp); - const gpt4_res = await dsNameFromDsSample.perform(trials, ds, gpt4, timestamp); - const gpt4turbo_res = await dsNameFromDsSample.perform(trials, ds, gpt4turbo, timestamp); + logger.info("Starting") + const timestamp = Date.now() + const gpt35turbo_res = await dsNameFromDsSample.perform( + trials, + ds, + gpt35turbo, + timestamp, + ) + const gpt4_res = await dsNameFromDsSample.perform(trials, ds, gpt4, timestamp) + const gpt4turbo_res = await dsNameFromDsSample.perform( + trials, + ds, + gpt4turbo, + timestamp, + ) - logger.info({ ...gpt35turbo_res.combinedResult.resultTypes }, `gpt35turbo_res ${gpt35turbo_res.combinedResult.avg}`); - logger.info({ ...gpt4_res.combinedResult.resultTypes }, `gpt4_res ${gpt4_res.combinedResult.avg}`); - logger.info({ ...gpt4turbo_res.combinedResult.resultTypes }, `gpt4turbo_res ${gpt4turbo_res.combinedResult.avg}`); + logger.info( + { ...gpt35turbo_res.combinedResult.resultTypes }, + `gpt35turbo_res ${gpt35turbo_res.combinedResult.avg}`, + ) + logger.info( + { ...gpt4_res.combinedResult.resultTypes }, + `gpt4_res ${gpt4_res.combinedResult.avg}`, + ) + logger.info( + { ...gpt4turbo_res.combinedResult.resultTypes }, + `gpt4turbo_res ${gpt4turbo_res.combinedResult.avg}`, + ) } nameFromSample(rg65).then(() => { - logger.info('Done'); - process.exit(0); -}); - - - + logger.info("Done") + process.exit(0) +}) diff --git a/src/scripts/dsPaperFromDsName.ts b/src/scripts/dsPaperFromDsName.ts index b713274..46f2c62 100644 --- a/src/scripts/dsPaperFromDsName.ts +++ b/src/scripts/dsPaperFromDsName.ts @@ -1,29 +1,43 @@ -import { DatasetProfile } from "punuy-datasets/src/lib/types"; -import { dsPaperFromDsName } from "../lib/experiments"; -import { gpt35turbo, gpt4, gpt4turbo } from "../lib/models"; -import logger from "../lib/logger"; -import rg65 from "punuy-datasets/rg65"; +import { DatasetProfile } from "punuy-datasets/src/lib/types" +import { dsPaperFromDsName } from "../lib/experiments" +import { gpt35turbo, gpt4, gpt4turbo } from "../lib/models" +import logger from "../lib/logger" +import rg65 from "punuy-datasets/rg65" -const trials = process.argv[2] ? parseInt(process.argv[2]) : 3; +const trials = process.argv[2] ? parseInt(process.argv[2]) : 3 const paperFromName = async (ds: DatasetProfile) => { - - logger.info('Starting') - const timestamp = Date.now(); - const gpt35turbo_res = await dsPaperFromDsName.perform(trials, ds, gpt35turbo, timestamp); - const gpt4_res = await dsPaperFromDsName.perform(trials, ds, gpt4, timestamp); - const gpt4turbo_res = await dsPaperFromDsName.perform(trials, ds, gpt4turbo, timestamp); - - logger.info({ ...gpt35turbo_res.combinedResult.resultTypes }, `gpt35turbo_res ${gpt35turbo_res.combinedResult.avg}`); - logger.info({ ...gpt4_res.combinedResult.resultTypes }, `gpt4_res ${gpt4_res.combinedResult.avg}`); - logger.info({ ...gpt4turbo_res.combinedResult.resultTypes }, `gpt4turbo_res ${gpt4turbo_res.combinedResult.avg}`); + logger.info("Starting") + const timestamp = Date.now() + const gpt35turbo_res = await dsPaperFromDsName.perform( + trials, + ds, + gpt35turbo, + timestamp, + ) + const gpt4_res = await dsPaperFromDsName.perform(trials, ds, gpt4, timestamp) + const gpt4turbo_res = await dsPaperFromDsName.perform( + trials, + ds, + gpt4turbo, + timestamp, + ) + + logger.info( + { ...gpt35turbo_res.combinedResult.resultTypes }, + `gpt35turbo_res ${gpt35turbo_res.combinedResult.avg}`, + ) + logger.info( + { ...gpt4_res.combinedResult.resultTypes }, + `gpt4_res ${gpt4_res.combinedResult.avg}`, + ) + logger.info( + { ...gpt4turbo_res.combinedResult.resultTypes }, + `gpt4turbo_res ${gpt4turbo_res.combinedResult.avg}`, + ) } paperFromName(rg65).then(() => { - logger.info('Done'); - process.exit(0); -}); - - - - + logger.info("Done") + process.exit(0) +}) diff --git a/src/scripts/dsSampleFromDsName.ts b/src/scripts/dsSampleFromDsName.ts index e4422e4..641dfc0 100644 --- a/src/scripts/dsSampleFromDsName.ts +++ b/src/scripts/dsSampleFromDsName.ts @@ -1,26 +1,43 @@ -import { DatasetProfile } from "punuy-datasets/src/lib/types"; -import { dsSampleFromDsName, saveExperimentData } from "../lib/experiments"; -import { gpt35turbo, gpt4, gpt4turbo } from "../lib/models"; -import { rg65 } from "punuy-datasets"; -import logger from "../lib/logger"; +import { DatasetProfile } from "punuy-datasets/src/lib/types" +import { dsSampleFromDsName, saveExperimentData } from "../lib/experiments" +import { gpt35turbo, gpt4, gpt4turbo } from "../lib/models" +import { rg65 } from "punuy-datasets" +import logger from "../lib/logger" -const trials = process.argv[2] ? parseInt(process.argv[2]) : 3; +const trials = process.argv[2] ? parseInt(process.argv[2]) : 3 const sampleFromName = async (ds: DatasetProfile) => { + logger.info("Starting") + const timestamp = Date.now() + const gpt35turbo_res = await dsSampleFromDsName.perform( + trials, + ds, + gpt35turbo, + timestamp, + ) + const gpt4_res = await dsSampleFromDsName.perform(trials, ds, gpt4, timestamp) + const gpt4turbo_res = await dsSampleFromDsName.perform( + trials, + ds, + gpt4turbo, + timestamp, + ) - logger.info('Starting') - const timestamp = Date.now(); - const gpt35turbo_res = await dsSampleFromDsName.perform(trials, ds, gpt35turbo, timestamp); - const gpt4_res = await dsSampleFromDsName.perform(trials, ds, gpt4, timestamp); - const gpt4turbo_res = await dsSampleFromDsName.perform(trials, ds, gpt4turbo, timestamp); - - logger.info({ ...gpt35turbo_res.combinedResult.resultTypes }, `gpt35turbo_res ${gpt35turbo_res.combinedResult.avg}`); - logger.info({ ...gpt4_res.combinedResult.resultTypes }, `gpt4_res ${gpt4_res.combinedResult.avg}`); - logger.info({ ...gpt4turbo_res.combinedResult.resultTypes }, `gpt4turbo_res ${gpt4turbo_res.combinedResult.avg}`); + logger.info( + { ...gpt35turbo_res.combinedResult.resultTypes }, + `gpt35turbo_res ${gpt35turbo_res.combinedResult.avg}`, + ) + logger.info( + { ...gpt4_res.combinedResult.resultTypes }, + `gpt4_res ${gpt4_res.combinedResult.avg}`, + ) + logger.info( + { ...gpt4turbo_res.combinedResult.resultTypes }, + `gpt4turbo_res ${gpt4turbo_res.combinedResult.avg}`, + ) } - sampleFromName(rg65).then(() => { - logger.info('Done'); - process.exit(0); -}); + logger.info("Done") + process.exit(0) +}) diff --git a/src/scripts/dsSampleFromDsSample.ts b/src/scripts/dsSampleFromDsSample.ts index 9162ef3..1c112e7 100644 --- a/src/scripts/dsSampleFromDsSample.ts +++ b/src/scripts/dsSampleFromDsSample.ts @@ -1,26 +1,48 @@ -import { DatasetProfile } from "punuy-datasets/src/lib/types"; -import logger from "../lib/logger"; -import { gpt35turbo, gpt4, gpt4turbo } from "../lib/models"; -import { dsSampleFromDsSample } from "../lib/experiments"; -import { rg65 } from "punuy-datasets"; +import { DatasetProfile } from "punuy-datasets/src/lib/types" +import logger from "../lib/logger" +import { gpt35turbo, gpt4, gpt4turbo } from "../lib/models" +import { dsSampleFromDsSample } from "../lib/experiments" +import { rg65 } from "punuy-datasets" - -const trials = process.argv[2] ? parseInt(process.argv[2]) : 3; +const trials = process.argv[2] ? parseInt(process.argv[2]) : 3 const sampleFromSample = async (ds: DatasetProfile) => { - logger.info('Starting') - const timestamp = Date.now(); - const gpt35turbo_res = await dsSampleFromDsSample.perform(trials, ds, gpt35turbo, timestamp); - const gpt4_res = await dsSampleFromDsSample.perform(trials, ds, gpt4, timestamp); - const gpt4turbo_res = await dsSampleFromDsSample.perform(trials, ds, gpt4turbo, timestamp); + logger.info("Starting") + const timestamp = Date.now() + const gpt35turbo_res = await dsSampleFromDsSample.perform( + trials, + ds, + gpt35turbo, + timestamp, + ) + const gpt4_res = await dsSampleFromDsSample.perform( + trials, + ds, + gpt4, + timestamp, + ) + const gpt4turbo_res = await dsSampleFromDsSample.perform( + trials, + ds, + gpt4turbo, + timestamp, + ) - logger.info({ ...gpt35turbo_res.combinedResult.resultTypes }, `gpt35turbo_res ${gpt35turbo_res.combinedResult.avg}`); - logger.info({ ...gpt4_res.combinedResult.resultTypes }, `gpt4_res ${gpt4_res.combinedResult.avg}`); - logger.info({ ...gpt4turbo_res.combinedResult.resultTypes }, `gpt4turbo_res ${gpt4turbo_res.combinedResult.avg}`); + logger.info( + { ...gpt35turbo_res.combinedResult.resultTypes }, + `gpt35turbo_res ${gpt35turbo_res.combinedResult.avg}`, + ) + logger.info( + { ...gpt4_res.combinedResult.resultTypes }, + `gpt4_res ${gpt4_res.combinedResult.avg}`, + ) + logger.info( + { ...gpt4turbo_res.combinedResult.resultTypes }, + `gpt4turbo_res ${gpt4turbo_res.combinedResult.avg}`, + ) } sampleFromSample(rg65).then(() => { - logger.info('Done'); - process.exit(0); -}); - + logger.info("Done") + process.exit(0) +}) diff --git a/tsconfig.json b/tsconfig.json index c2f1f2e..72406d0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,10 +1,7 @@ { "compilerOptions": { "target": "es2016", - "lib": [ - "ES2017", - "DOM" - ], + "lib": ["ES2017", "DOM"], "module": "nodenext", "resolveJsonModule": true, "esModuleInterop": true, @@ -13,20 +10,13 @@ "declaration": true, "skipLibCheck": true, "paths": { - "*": [ - "src/@types/*" - ] + "*": ["src/@types/*"] }, "baseUrl": "./", "outDir": "dist", "sourceMap": true, - "noEmitOnError": true, + "noEmitOnError": true }, - "include": [ - "src" - ], - "exclude": [ - "node_modules", - "dist" - ] + "include": ["src"], + "exclude": ["node_modules", "dist"] }