diff --git a/declarations.d.ts b/declarations.d.ts index 3cd4cb86..35b55401 100644 --- a/declarations.d.ts +++ b/declarations.d.ts @@ -1,2 +1,2 @@ declare module 'langchain/embeddings/openai'; -declare module 'langchain/embeddings/hf'; \ No newline at end of file +declare module 'langchain/embeddings/hf'; diff --git a/package-lock.json b/package-lock.json index 2c68d1f3..60a74937 100644 --- a/package-lock.json +++ b/package-lock.json @@ -335,6 +335,7 @@ "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.27.3.tgz", "integrity": "sha512-IjLt0gd3L4jlOfilxVXTifn42FnVffMgDC04RJK1KDZpmkBWLv0XC92MVVmkxrFZNS/7l3xWgP/I3nqtX1sQHw==", "license": "MIT", + "peer": true, "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", @@ -350,6 +351,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~5.26.4" } @@ -358,7 +360,8 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@apollo/cache-control-types": { "version": "1.0.3", @@ -2063,6 +2066,7 @@ "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.3.1" } @@ -2139,7 +2143,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -2657,6 +2660,7 @@ "resolved": "https://registry.npmjs.org/@browserbasehq/sdk/-/sdk-2.6.0.tgz", "integrity": "sha512-83iXP5D7xMm8Wyn66TUaUrgoByCmAJuoMoZQI3sGg3JAiMlTfnCIMqyVBoNSaItaPIkaCnrsj6LiusmXV2X9YA==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", @@ -2672,6 +2676,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~5.26.4" } @@ -2680,7 +2685,8 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@browserbasehq/stagehand": { "version": "1.14.0", @@ -2716,7 +2722,8 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz", "integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@colors/colors": { "version": "1.5.0", @@ -3021,7 +3028,6 @@ "resolved": "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-8.19.1.tgz", "integrity": "sha512-+1j9NnQVOX+lbWB8LhCM7IkUmjU05Y4+BmSLfusq0msCsQb1Va+OUKFCoOXjCJqQrcgdRdQCjYYyolQ/npQALQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@elastic/transport": "^8.9.6", "apache-arrow": "18.x - 21.x", @@ -3246,7 +3252,6 @@ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", @@ -3286,7 +3291,6 @@ "resolved": "https://registry.npmjs.org/@huggingface/inference/-/inference-4.13.13.tgz", "integrity": "sha512-kxa3hkQEgD/B2x6QTZQBnu4Wx/Uc7pOAqmLS8T3VkTM4weshJzaeYH/nEDKGuChUKJza0IglytRViSCiT8KLjg==", "license": "MIT", - "peer": true, "dependencies": { "@huggingface/jinja": "^0.5.5", "@huggingface/tasks": "^0.19.85" @@ -3384,6 +3388,7 @@ "resolved": "https://registry.npmjs.org/@ibm-cloud/watsonx-ai/-/watsonx-ai-1.7.8.tgz", "integrity": "sha512-UpU/hTHRrCwzkqV1+H/CGbHIGRKty6SX1Aea2CBbyRonsEPIPQtFfhz8FHhs+o6Ca/TCupHNlcLAQUFektZmEQ==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@types/node": "^18.0.0", "extend": "3.0.2", @@ -3399,6 +3404,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~5.26.4" } @@ -3407,7 +3413,8 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@img/colour": { "version": "1.0.0", @@ -5257,6 +5264,7 @@ "https://github.com/sponsors/ctavan" ], "license": "MIT", + "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -5463,6 +5471,19 @@ "ioredis": ">=5.0.0" } }, + "node_modules/@nestjs-modules/ioredis/node_modules/@nestjs/axios": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.3.tgz", + "integrity": "sha512-RZ/63c1tMxGLqyG3iOCVt7A72oy4x1eM6QEhd4KzCYpaVWW0igq0WSREeRoEZhIxRcZfDfIIkvsOMiM7yfVGZQ==", + "license": "MIT", + "optional": true, + "peer": true, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "axios": "^1.3.1", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, "node_modules/@nestjs-modules/ioredis/node_modules/@nestjs/terminus": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/@nestjs/terminus/-/terminus-10.2.0.tgz", @@ -5534,6 +5555,32 @@ } } }, + "node_modules/@nestjs-modules/ioredis/node_modules/@nestjs/typeorm": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", + "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "uuid": "9.0.1" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", + "reflect-metadata": "^0.1.13 || ^0.2.0", + "rxjs": "^7.2.0", + "typeorm": "^0.3.0" + } + }, + "node_modules/@nestjs-modules/ioredis/node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==", + "license": "Apache-2.0", + "optional": true, + "peer": true + }, "node_modules/@nestjs-modules/ioredis/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -5544,6 +5591,7 @@ ], "license": "MIT", "optional": true, + "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -5586,7 +5634,6 @@ "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-4.0.1.tgz", "integrity": "sha512-68pFJgu+/AZbWkGu65Z3r55bTsCPlgyKaV4BSG8yUAD72q1PPuyVRgUwFv6BxdnibTUHlyxm06FmYWNC+bjN7A==", "license": "MIT", - "peer": true, "peerDependencies": { "@nestjs/common": "^10.0.0 || ^11.0.0", "axios": "^1.3.1", @@ -5843,7 +5890,6 @@ "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.22.tgz", "integrity": "sha512-fxJ4v85nDHaqT1PmfNCQ37b/jcv2OojtXTaK1P2uAXhzLf9qq6WNUOFvxBrV4fhQek1EQoT1o9oj5xAZmv3NRw==", "license": "MIT", - "peer": true, "dependencies": { "file-type": "20.4.1", "iterare": "1.2.1", @@ -5902,7 +5948,6 @@ "integrity": "sha512-6IX9+VwjiKtCjx+mXVPncpkQ5ZjKfmssOZPFexmT+6T9H9wZ3svpYACAo7+9e7Nr9DZSoRZw3pffkJP7Z0UjaA==", "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "@nuxtjs/opencollective": "0.3.2", "fast-safe-stringify": "2.1.1", @@ -5964,7 +6009,6 @@ "resolved": "https://registry.npmjs.org/@nestjs/graphql/-/graphql-12.2.2.tgz", "integrity": "sha512-lUDy/1uqbRA1kBKpXcmY0aHhcPbfeG52Wg5+9Jzd1d57dwSjCAmuO+mWy5jz9ugopVCZeK0S/kdAMvA+r9fNdA==", "license": "MIT", - "peer": true, "dependencies": { "@graphql-tools/merge": "9.0.11", "@graphql-tools/schema": "10.0.10", @@ -6174,7 +6218,6 @@ "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.22.tgz", "integrity": "sha512-ySSq7Py/DFozzZdNDH67m/vHoeVdphDniWBnl6q5QVoXldDdrZIHLXLRMPayTDh5A95nt7jjJzmD4qpTbNQ6tA==", "license": "MIT", - "peer": true, "dependencies": { "body-parser": "1.20.4", "cors": "2.8.5", @@ -6720,7 +6763,6 @@ "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-11.0.0.tgz", "integrity": "sha512-SOeUQl70Lb2OfhGkvnh4KXWlsd+zA08RuuQgT7kKbzivngxzSo1Oc7Usu5VxCxACQC9wc2l9esOHILSJeK7rJA==", "license": "MIT", - "peer": true, "peerDependencies": { "@nestjs/common": "^10.0.0 || ^11.0.0", "@nestjs/core": "^10.0.0 || ^11.0.0", @@ -6734,7 +6776,6 @@ "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.22.tgz", "integrity": "sha512-OLd4i0Faq7vgdtB5vVUrJ54hWEtcXy9poJ6n7kbbh/5ms+KffUl+wwGsbe7uSXLrkoyI8xXU6fZPkFArI+XiRg==", "license": "MIT", - "peer": true, "dependencies": { "iterare": "1.2.1", "object-hash": "3.0.0", @@ -6855,7 +6896,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -7792,6 +7832,7 @@ "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.11.0.tgz", "integrity": "sha512-KYiVilAhAFN3057afUb/tfYJpsEyTkQB+tQcn5gVVA7DgcNOAj8lLxe4j8ov8BF6I9C1Fe/kwlbuAICcTMX8Lw==", "license": "MIT", + "peer": true, "engines": { "node": ">= 18" }, @@ -7825,6 +7866,7 @@ "resolved": "https://registry.npmjs.org/@redis/json/-/json-5.11.0.tgz", "integrity": "sha512-1iAy9kAtcD0quB21RbPTbUqqy+T2Uu2JxucwE+B4A+VaDbIRvpZR6DMqV8Iqaws2YxJYB3GC5JVNzPYio2ErUg==", "license": "MIT", + "peer": true, "engines": { "node": ">= 18" }, @@ -7837,6 +7879,7 @@ "resolved": "https://registry.npmjs.org/@redis/search/-/search-5.11.0.tgz", "integrity": "sha512-g1l7f3Rnyk/xI99oGHIgWHSKFl45Re5YTIcO8j/JE8olz389yUFyz2+A6nqVy/Zi031VgPDWscbbgOk8hlhZ3g==", "license": "MIT", + "peer": true, "engines": { "node": ">= 18" }, @@ -7849,6 +7892,7 @@ "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-5.11.0.tgz", "integrity": "sha512-TWFeOcU4xkj0DkndnOyhtxvX1KWD+78UHT3XX3x3XRBUGWeQrKo3jqzDsZwxbggUgf9yLJr/akFHXru66X5UQA==", "license": "MIT", + "peer": true, "engines": { "node": ">= 18" }, @@ -8028,6 +8072,7 @@ "integrity": "sha512-8janZoJw85nJmQZc4L8TuePp2pk1nxLgkxIR0TUjKJ5Dkj5oelB9WtiSSGXCQvNsJl0VSTvK/2ueMXxvpa9GVw==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "@aws-crypto/crc32": "3.0.0", "@smithy/types": "^2.12.0", @@ -8041,6 +8086,7 @@ "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", @@ -8052,7 +8098,8 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "license": "0BSD", - "optional": true + "optional": true, + "peer": true }, "node_modules/@smithy/eventstream-codec/node_modules/@aws-crypto/util": { "version": "3.0.0", @@ -8060,6 +8107,7 @@ "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-utf8-browser": "^3.0.0", @@ -8071,7 +8119,8 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "license": "0BSD", - "optional": true + "optional": true, + "peer": true }, "node_modules/@smithy/eventstream-codec/node_modules/@smithy/types": { "version": "2.12.0", @@ -8079,6 +8128,7 @@ "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8092,6 +8142,7 @@ "integrity": "sha512-7iKXR+/4TpLK194pVjKiasIyqMtTYJsgKgM242Y9uzt5dhHnUDvMNb+3xIhRJ9QhvqGii/5cRUt4fJn3dtXNHQ==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8502,6 +8553,7 @@ "integrity": "sha512-Xy5XK1AFWW2nlY/biWZXu6/krgbaf2dg0q492D8M5qthsnU2H+UgFeZLbM76FnH7s6RO/xhQRkj+T6KBO3JzgQ==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "@smithy/types": "^2.12.0", "tslib": "^2.6.2" @@ -8516,6 +8568,7 @@ "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8581,6 +8634,7 @@ "integrity": "sha512-ui/NlpILU+6HAQBfJX8BBsDXuKSNrjTSuOYArRblcrErwKFutjrCNb/OExfVRyj9+26F9J+ZmfWT+fKWuDrH3Q==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "@smithy/types": "^2.12.0", @@ -8600,6 +8654,7 @@ "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8613,6 +8668,7 @@ "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8626,6 +8682,7 @@ "integrity": "sha512-7iKXR+/4TpLK194pVjKiasIyqMtTYJsgKgM242Y9uzt5dhHnUDvMNb+3xIhRJ9QhvqGii/5cRUt4fJn3dtXNHQ==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8639,6 +8696,7 @@ "integrity": "sha512-L1qpleXf9QD6LwLCJ5jddGkgWyuSvWBkJwWAZ6kFkdifdso+sk3L3O1HdmPvCdnCK3IS4qWyPxev01QMnfHSBw==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "@smithy/types": "^2.12.0", "tslib": "^2.6.2" @@ -8653,6 +8711,7 @@ "integrity": "sha512-jtmJMyt1xMD/d8OtbVJ2gFZOSKc+ueYJZPW20ULW1GOp/q/YIM0wNh+u8ZFao9UaIGz4WoPW8hC64qlWLIfoDA==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -9185,6 +9244,7 @@ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/ms": "*" } @@ -9195,7 +9255,6 @@ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -9405,7 +9464,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.33.tgz", "integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==", "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -9572,7 +9630,8 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/uuid": { "version": "10.0.0", @@ -9648,7 +9707,6 @@ "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", @@ -10086,6 +10144,7 @@ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", + "peer": true, "dependencies": { "event-target-shim": "^5.0.0" }, @@ -10126,7 +10185,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -10149,6 +10207,7 @@ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10.13.0" }, @@ -10184,6 +10243,7 @@ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "license": "MIT", + "peer": true, "dependencies": { "humanize-ms": "^1.2.1" }, @@ -10197,7 +10257,6 @@ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -10516,7 +10575,6 @@ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", "license": "MIT", - "peer": true, "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", @@ -11063,7 +11121,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -11129,7 +11186,6 @@ "resolved": "https://registry.npmjs.org/bull/-/bull-4.16.5.tgz", "integrity": "sha512-lDsx2BzkKe7gkCYiT5Acj02DpTwDznl/VNN7Psn7M3USPG7Vs/BaClZJJTAG+ufAR9++N1/NiUTdaFBWDIl5TQ==", "license": "MIT", - "peer": true, "dependencies": { "cron-parser": "^4.9.0", "get-port": "^5.1.1", @@ -11177,7 +11233,6 @@ "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-7.2.8.tgz", "integrity": "sha512-0HDaDLBBY/maa/LmUVAr70XUOwsiQD+jyzCBjmUErYZUKdMS9dT59PqW59PpVqfGM7ve6H0J6307JTpkCYefHQ==", "license": "MIT", - "peer": true, "dependencies": { "@cacheable/utils": "^2.3.3", "keyv": "^5.5.5" @@ -11224,7 +11279,6 @@ "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz", "integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==", "license": "MIT", - "peer": true, "dependencies": { "cluster-key-slot": "1.1.2", "generic-pool": "3.9.0", @@ -11529,15 +11583,13 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/class-validator": { "version": "0.14.3", "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.3.tgz", "integrity": "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==", "license": "MIT", - "peer": true, "dependencies": { "@types/validator": "^13.15.3", "libphonenumber-js": "^1.11.1", @@ -12055,7 +12107,6 @@ "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", @@ -12281,6 +12332,7 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -12335,7 +12387,6 @@ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -12488,7 +12539,6 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=12" }, @@ -12753,7 +12803,8 @@ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/es-object-atoms": { "version": "1.1.1", @@ -12817,7 +12868,6 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -12874,7 +12924,6 @@ "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -13195,6 +13244,7 @@ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=6" } @@ -13344,7 +13394,6 @@ "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.19.0.tgz", "integrity": "sha512-0csaMkGq+vaiZTmSMMGkfdCOabYv192VbytFypcvI0MANrp+4i/7yEkJ0sbAEhycQjntaKGzYfjfXQyVb7BHMA==", "license": "MIT", - "peer": true, "dependencies": { "cookie": "~0.7.2", "cookie-signature": "~1.0.7", @@ -13466,7 +13515,8 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/external-editor": { "version": "3.1.0", @@ -13579,7 +13629,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "fast-xml-builder": "^1.0.0", "strnum": "^2.1.2" @@ -14020,7 +14069,8 @@ "version": "1.7.2", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/form-data/node_modules/mime-db": { "version": "1.52.0", @@ -14048,6 +14098,7 @@ "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", "license": "MIT", + "peer": true, "dependencies": { "node-domexception": "1.0.0", "web-streams-polyfill": "4.0.0-beta.3" @@ -14417,7 +14468,6 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.0.tgz", "integrity": "sha512-uSisMYERbaB9bkA9M4/4dnqyktaEkf1kMHNKq/7DHyxVeWqHQ2mBmVqm5u6/FVHwF3iCNalKcg82Zfl+tffWoA==", "license": "MIT", - "peer": true, "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } @@ -14485,7 +14535,6 @@ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "license": "MIT", - "peer": true, "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", @@ -14650,6 +14699,7 @@ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "license": "MIT", + "peer": true, "dependencies": { "ms": "^2.0.0" } @@ -14675,6 +14725,7 @@ "resolved": "https://registry.npmjs.org/ibm-cloud-sdk-core/-/ibm-cloud-sdk-core-5.4.8.tgz", "integrity": "sha512-tLMlZv13cV6S1UPj/bhv8XfV9Z1BDDs/4DxHKWnCw7QlJMzmGdHLPX386x9nrFMQMPZ48eAH+Thsa06tzUZkaA==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@types/debug": "^4.1.12", "@types/node": "^18.19.80", @@ -14701,6 +14752,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~5.26.4" } @@ -14710,6 +14762,7 @@ "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", "license": "MIT", + "peer": true, "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", @@ -14740,13 +14793,15 @@ "url": "https://feross.org/support" } ], - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/ibm-cloud-sdk-core/node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -14756,6 +14811,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -14768,6 +14824,7 @@ "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", "license": "MIT", + "peer": true, "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^4.1.0" @@ -14785,6 +14842,7 @@ "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", "license": "MIT", + "peer": true, "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" @@ -14801,7 +14859,8 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/iconv-lite": { "version": "0.4.24", @@ -14827,7 +14886,6 @@ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "devOptional": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 4" } @@ -15020,7 +15078,6 @@ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.9.3.tgz", "integrity": "sha512-VI5tMCdeoxZWU5vjHWsiE/Su76JGhBvWF1MJnV9ZtGltHk9BmD48oDq8Tj8haZ85aceXZMxLNDQZRVo5QKNgXA==", "license": "MIT", - "peer": true, "dependencies": { "@ioredis/commands": "1.5.0", "cluster-key-slot": "^1.1.0", @@ -15308,7 +15365,8 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", @@ -15427,7 +15485,6 @@ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -16820,7 +16877,6 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "license": "MIT", - "peer": true, "dependencies": { "@keyv/serialize": "^1.1.1" } @@ -17377,8 +17433,7 @@ "version": "4.17.23", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.camelcase": { "version": "4.3.0", @@ -18163,6 +18218,7 @@ "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", "license": "MIT", + "peer": true, "bin": { "mustache": "bin/mustache" } @@ -18287,6 +18343,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=10.5.0" } @@ -18586,6 +18643,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~5.26.4" } @@ -18594,7 +18652,8 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/openapi-types": { "version": "12.1.3", @@ -18875,7 +18934,6 @@ "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", "license": "MIT", - "peer": true, "dependencies": { "passport-strategy": "1.x.x", "pause": "0.0.1", @@ -18990,7 +19048,6 @@ "resolved": "https://registry.npmjs.org/pdf-parse/-/pdf-parse-1.1.1.tgz", "integrity": "sha512-v6ZJ/efsBpGrGGknjtq9J/oC8tZWq0KWL5vQrk2GlzLEQPUDB1ex+13Rmidl1neNN358Jn9EHZw5y07FFtaC7A==", "license": "MIT", - "peer": true, "dependencies": { "debug": "^3.1.0", "node-ensure": "^0.0.0" @@ -19013,6 +19070,7 @@ "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", "license": "MIT", + "peer": true, "engines": { "node": ">=8" }, @@ -19026,7 +19084,6 @@ "resolved": "https://registry.npmjs.org/pg/-/pg-8.18.0.tgz", "integrity": "sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ==", "license": "MIT", - "peer": true, "dependencies": { "pg-connection-string": "^2.11.0", "pg-pool": "^3.11.0", @@ -19244,6 +19301,7 @@ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", "license": "Apache-2.0", + "peer": true, "dependencies": { "playwright-core": "1.58.2" }, @@ -19262,6 +19320,7 @@ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "license": "Apache-2.0", + "peer": true, "bin": { "playwright-core": "cli.js" }, @@ -19279,6 +19338,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } @@ -19412,7 +19472,6 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -19456,6 +19515,7 @@ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6.0" } @@ -19541,6 +19601,7 @@ "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", "license": "MIT", + "peer": true, "dependencies": { "punycode": "^2.3.1" }, @@ -19612,7 +19673,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -19733,6 +19795,7 @@ "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz", "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==", "license": "MIT", + "peer": true, "dependencies": { "readable-stream": "^4.7.0" }, @@ -19763,6 +19826,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -19773,6 +19837,7 @@ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.8.x" } @@ -19795,13 +19860,15 @@ "url": "https://feross.org/support" } ], - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", "license": "MIT", + "peer": true, "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", @@ -19930,7 +19997,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/resolve": { "version": "1.22.11", @@ -20020,6 +20088,7 @@ "resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-2.6.0.tgz", "integrity": "sha512-pOLi+Gdll3JekwuFjXO3fTq+L9lzMQGcSq7M5gIjExcl3Gu1hd4XXuf5o3+LuSBsaULQH7DiNbsqPd1chVpQGQ==", "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=10.7.0" }, @@ -20178,7 +20247,6 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -20257,7 +20325,6 @@ "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -21676,6 +21743,7 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "license": "BSD-3-Clause", + "peer": true, "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -21691,6 +21759,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "license": "MIT", + "peer": true, "engines": { "node": ">= 4.0.0" } @@ -21856,7 +21925,6 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -22081,7 +22149,6 @@ "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.28.tgz", "integrity": "sha512-6GH7wXhtfq2D33ZuRXYwIsl/qM5685WZcODZb7noOOcRMteM9KF2x2ap3H0EBjnSV0VO4gNAfJT5Ukp0PkOlvg==", "license": "MIT", - "peer": true, "dependencies": { "@sqltools/formatter": "^1.2.5", "ansis": "^4.2.0", @@ -22265,7 +22332,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -22435,6 +22501,7 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "license": "MIT", + "peer": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -22614,6 +22681,7 @@ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", "license": "MIT", + "peer": true, "engines": { "node": ">= 14" } @@ -22700,6 +22768,7 @@ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -22714,6 +22783,7 @@ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=4.0" } @@ -22724,6 +22794,7 @@ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.8.x" } @@ -22734,6 +22805,7 @@ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -22744,6 +22816,7 @@ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -22757,6 +22830,7 @@ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -22960,6 +23034,7 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "license": "MIT", + "peer": true, "engines": { "node": ">=10.0.0" }, @@ -23114,7 +23189,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -23124,6 +23198,7 @@ "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", "license": "ISC", + "peer": true, "peerDependencies": { "zod": "^3.25 || ^4" } diff --git a/src/ab-testing/ab-testing.controller.ts b/src/ab-testing/ab-testing.controller.ts index b1e11734..992aba45 100644 --- a/src/ab-testing/ab-testing.controller.ts +++ b/src/ab-testing/ab-testing.controller.ts @@ -10,16 +10,21 @@ import { Logger, HttpCode, HttpStatus, + UseGuards, + Request, } from '@nestjs/common'; -import { ABTestingService } from './ab-testing.service'; +import { ABTestingService, CreateExperimentDto } from './ab-testing.service'; import { ExperimentService } from './experiments/experiment.service'; import { StatisticalAnalysisService } from './analysis/statistical-analysis.service'; import { AutomatedDecisionService } from './automation/automated-decision.service'; import { ABTestingReportsService } from './reporting/ab-testing-reports.service'; -import { CreateExperimentDto } from './ab-testing.service'; -import { ExperimentStatus, ExperimentType } from './entities/experiment.entity'; +import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; +import { RolesGuard } from '../auth/guards/roles.guard'; +import { Roles } from '../auth/decorators/roles.decorator'; +import { UserRole } from '../users/entities/user.entity'; @Controller('ab-testing') +@UseGuards(JwtAuthGuard, RolesGuard) export class ABTestingController { private readonly logger = new Logger(ABTestingController.name); @@ -32,6 +37,7 @@ export class ABTestingController { ) {} @Get('experiments') + @Roles(UserRole.ADMIN, UserRole.TEACHER) async getAllExperiments() { this.logger.log('Fetching all experiments'); return await this.abTestingService.getAllExperiments(); @@ -45,13 +51,15 @@ export class ABTestingController { @Post('experiments') @HttpCode(HttpStatus.CREATED) - async createExperiment(@Body() createExperimentDto: CreateExperimentDto) { + @Roles(UserRole.ADMIN) + async createExperiment(@Request() req, @Body() createExperimentDto: CreateExperimentDto) { this.logger.log(`Creating new experiment: ${createExperimentDto.name}`); return await this.abTestingService.createExperiment(createExperimentDto); } @Post('experiments/:id/start') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async startExperiment(@Param('id') id: string) { this.logger.log(`Starting experiment: ${id}`); return await this.abTestingService.startExperiment(id); @@ -59,6 +67,7 @@ export class ABTestingController { @Post('experiments/:id/stop') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async stopExperiment(@Param('id') id: string) { this.logger.log(`Stopping experiment: ${id}`); return await this.abTestingService.stopExperiment(id); @@ -66,6 +75,7 @@ export class ABTestingController { @Put('experiments/:id') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async updateExperiment(@Param('id') id: string, @Body() updateData: any) { this.logger.log(`Updating experiment: ${id}`); return await this.experimentService.updateExperiment(id, updateData); @@ -73,6 +83,7 @@ export class ABTestingController { @Delete('experiments/:id') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async deleteExperiment(@Param('id') id: string) { this.logger.log(`Deleting experiment: ${id}`); // Implementation would go here @@ -87,6 +98,7 @@ export class ABTestingController { @Post('experiments/:id/variants') @HttpCode(HttpStatus.CREATED) + @Roles(UserRole.ADMIN) async addVariant(@Param('id') experimentId: string, @Body() variantData: any) { this.logger.log(`Adding variant to experiment: ${experimentId}`); return await this.experimentService.addVariant(experimentId, variantData); @@ -94,6 +106,7 @@ export class ABTestingController { @Delete('variants/:id') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async removeVariant(@Param('id') variantId: string) { this.logger.log(`Removing variant: ${variantId}`); await this.experimentService.removeVariant(variantId); @@ -102,6 +115,7 @@ export class ABTestingController { @Put('experiments/:id/traffic-allocation') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async updateTrafficAllocation( @Param('id') experimentId: string, @Body() allocations: Record, @@ -125,6 +139,7 @@ export class ABTestingController { @Post('experiments/:id/auto-select-winner') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async autoSelectWinner(@Param('id') id: string, @Body() criteria?: any) { this.logger.log(`Auto-selecting winner for experiment: ${id}`); return await this.automatedDecisionService.autoSelectWinner(id, criteria); @@ -138,6 +153,7 @@ export class ABTestingController { @Post('experiments/:id/auto-allocate-traffic') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async autoAllocateTraffic(@Param('id') id: string) { this.logger.log(`Auto-allocating traffic for experiment: ${id}`); await this.automatedDecisionService.autoAllocateTraffic(id); @@ -145,6 +161,7 @@ export class ABTestingController { } @Get('reports/dashboard') + @Roles(UserRole.ADMIN, UserRole.TEACHER) async getDashboardSummary(@Query() filters?: any) { this.logger.log('Generating dashboard summary'); return await this.reportsService.getDashboardSummary(filters); @@ -180,6 +197,7 @@ export class ABTestingController { @Post('experiments/:id/pause') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async pauseExperiment(@Param('id') id: string) { this.logger.log(`Pausing experiment: ${id}`); return await this.experimentService.pauseExperiment(id); @@ -187,6 +205,7 @@ export class ABTestingController { @Post('experiments/:id/resume') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async resumeExperiment(@Param('id') id: string) { this.logger.log(`Resuming experiment: ${id}`); return await this.experimentService.resumeExperiment(id); @@ -194,12 +213,14 @@ export class ABTestingController { @Post('experiments/:id/archive') @HttpCode(HttpStatus.OK) + @Roles(UserRole.ADMIN) async archiveExperiment(@Param('id') id: string) { this.logger.log(`Archiving experiment: ${id}`); return await this.experimentService.archiveExperiment(id); } @Get('experiments/:id/assign-user/:userId') + @Roles(UserRole.ADMIN) async assignUserToVariant(@Param('id') experimentId: string, @Param('userId') userId: string) { this.logger.log(`Assigning user ${userId} to variant for experiment: ${experimentId}`); return await this.abTestingService.assignUserToVariant(experimentId, userId); diff --git a/src/ab-testing/ab-testing.service.ts b/src/ab-testing/ab-testing.service.ts index ea811f04..2b84e3ea 100644 --- a/src/ab-testing/ab-testing.service.ts +++ b/src/ab-testing/ab-testing.service.ts @@ -1,9 +1,8 @@ import { Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { Experiment } from './entities/experiment.entity'; +import { Experiment, ExperimentStatus, ExperimentType } from './entities/experiment.entity'; import { ExperimentVariant } from './entities/experiment-variant.entity'; -import { ExperimentStatus, ExperimentType } from './entities/experiment.entity'; export interface CreateExperimentDto { name: string; @@ -163,7 +162,7 @@ export class ABTestingService { /** * Gets active experiments for a user */ - async getActiveExperimentsForUser(userId: string): Promise { + async getActiveExperimentsForUser(_userId: string): Promise { return await this.experimentRepository.find({ where: { status: ExperimentStatus.RUNNING, diff --git a/src/ab-testing/automation/automated-decision.service.ts b/src/ab-testing/automation/automated-decision.service.ts index d4d1d245..b5948848 100644 --- a/src/ab-testing/automation/automated-decision.service.ts +++ b/src/ab-testing/automation/automated-decision.service.ts @@ -1,10 +1,9 @@ import { Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { Experiment } from '../entities/experiment.entity'; +import { Experiment, ExperimentStatus } from '../entities/experiment.entity'; import { ExperimentVariant } from '../entities/experiment-variant.entity'; import { StatisticalAnalysisService } from '../analysis/statistical-analysis.service'; -import { ExperimentStatus } from '../entities/experiment.entity'; export interface WinnerSelectionCriteria { confidenceLevel: number; @@ -162,9 +161,9 @@ export class AutomatedDecisionService { * Calculates effect size for a specific variant compared to control */ private async calculateEffectSizeForVariant( - experimentId: string, - variantId: string, - controlId: string, + _experimentId: string, + _variantId: string, + _controlId: string, ): Promise { // This would use the statistical analysis service to calculate effect size // For now, returning a placeholder value @@ -221,9 +220,9 @@ export class AutomatedDecisionService { } // Check if all variants have sufficient sample size - const minimumSampleSize = experiment.minimumSampleSize || 100; + const _minimumSampleSize = experiment.minimumSampleSize || 100; - for (const variant of experiment.variants) { + for (const _variant of experiment.variants) { // This would check actual sample sizes from metrics // For now, we'll assume variants are ready } diff --git a/src/ab-testing/experiments/experiment.service.ts b/src/ab-testing/experiments/experiment.service.ts index 2869f975..6e307f12 100644 --- a/src/ab-testing/experiments/experiment.service.ts +++ b/src/ab-testing/experiments/experiment.service.ts @@ -1,11 +1,10 @@ import { Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { Experiment } from '../entities/experiment.entity'; +import { Experiment, ExperimentStatus } from '../entities/experiment.entity'; import { ExperimentVariant } from '../entities/experiment-variant.entity'; import { ExperimentMetric } from '../entities/experiment-metric.entity'; import { VariantMetric } from '../entities/variant-metric.entity'; -import { ExperimentStatus, ExperimentType } from '../entities/experiment.entity'; @Injectable() export class ExperimentService { diff --git a/src/ab-testing/reporting/ab-testing-reports.service.ts b/src/ab-testing/reporting/ab-testing-reports.service.ts index e47c0d2d..ed6b1f1c 100644 --- a/src/ab-testing/reporting/ab-testing-reports.service.ts +++ b/src/ab-testing/reporting/ab-testing-reports.service.ts @@ -1,11 +1,10 @@ import { Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { Experiment } from '../entities/experiment.entity'; +import { Experiment, ExperimentStatus, ExperimentType } from '../entities/experiment.entity'; import { ExperimentVariant } from '../entities/experiment-variant.entity'; import { StatisticalAnalysisService } from '../analysis/statistical-analysis.service'; import { AutomatedDecisionService } from '../automation/automated-decision.service'; -import { ExperimentStatus, ExperimentType } from '../entities/experiment.entity'; export interface ReportFilters { status?: ExperimentStatus; @@ -267,9 +266,9 @@ export class ABTestingReportsService { * Calculates improvement percentage between winner and control */ private async calculateImprovementPercentage( - experimentId: string, - winnerId: string, - controlId: string, + _experimentId: string, + _winnerId: string, + _controlId: string, ): Promise { // This would fetch actual metric data and calculate improvement // For now, returning a placeholder value diff --git a/src/app.module.ts b/src/app.module.ts index 0273f4fb..a78f600d 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,7 +1,8 @@ import { Module } from '@nestjs/common'; +import { APP_INTERCEPTOR, APP_GUARD } from '@nestjs/core'; import { ConfigModule } from '@nestjs/config'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { APP_INTERCEPTOR } from '@nestjs/core'; +import { redisStore } from 'cache-manager-redis-store'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @@ -26,11 +27,9 @@ import { CacheModule } from '@nestjs/cache-manager'; import { RateLimitingModule } from './rate-limiting/services/rate-limiting.module'; import { envValidationSchema } from './config/env.validation'; import { HealthModule } from './health/health.module'; -import { cacheConfig } from './config/cache.config'; import { SessionModule } from './session/session.module'; import { createBullRedisClient } from './common/utils/bull-redis.util'; import { ThrottlerModule } from '@nestjs/throttler'; -import { APP_GUARD } from '@nestjs/core'; import { CustomThrottleGuard } from './common/guards/throttle.guard'; @Module({ @@ -72,20 +71,12 @@ import { CustomThrottleGuard } from './common/guards/throttle.guard'; port: parseInt(process.env.REDIS_PORT || '6379'), }), SessionModule, - ThrottlerModule.forRootAsync({ - imports: [ConfigModule], - useFactory: () => ({ + ThrottlerModule.forRoot([ + { ttl: parseInt(process.env.THROTTLE_TTL || '60'), limit: parseInt(process.env.THROTTLE_LIMIT || '10'), - storage: { - type: 'redis', - options: { - host: process.env.REDIS_HOST || 'localhost', - port: parseInt(process.env.REDIS_PORT || '6379'), - }, - }, - }), - }), + }, + ]), HealthModule, SyncModule, MediaModule, diff --git a/src/assessment/assessment.controller.ts b/src/assessment/assessment.controller.ts index 50338b7c..46c45cf2 100644 --- a/src/assessment/assessment.controller.ts +++ b/src/assessment/assessment.controller.ts @@ -1,22 +1,30 @@ -import { Body, Controller, Get, Param, Post } from '@nestjs/common'; +import { Body, Controller, Get, Param, Post, UseGuards, Request } from '@nestjs/common'; import { AssessmentsService } from './assessments.service'; +import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; @Controller('assessments') export class AssessmentsController { constructor(private readonly service: AssessmentsService) {} @Post(':id/start') - start(@Param('id') id: string, @Body('studentId') studentId: string) { + @UseGuards(JwtAuthGuard) + start(@Request() req, @Param('id') id: string) { + const studentId = req.user.id; + if (!studentId) { + throw new Error('User not authenticated'); + } return this.service.startAssessment(studentId, id); } @Post('attempts/:id/submit') - submit(@Param('id') id: string, @Body('answers') answers: any[]) { + @UseGuards(JwtAuthGuard) + submit(@Request() req, @Param('id') id: string, @Body('answers') answers: any[]) { return this.service.submitAssessment(id, answers); } @Get('attempts/:id') - results(@Param('id') id: string) { + @UseGuards(JwtAuthGuard) + results(@Request() req, @Param('id') id: string) { return this.service.getResults(id); } } diff --git a/src/assessment/entities/answer.entity.ts b/src/assessment/entities/answer.entity.ts index 06a02ce6..e6ebc7b0 100644 --- a/src/assessment/entities/answer.entity.ts +++ b/src/assessment/entities/answer.entity.ts @@ -1,4 +1,4 @@ -import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { AssessmentAttempt } from './assessment-attempt.entity'; import { Question } from './question.entity'; @Entity() diff --git a/src/audit-log/tests/audit-log.test.ts b/src/audit-log/tests/audit-log.test.ts index 226b8d16..5a070551 100644 --- a/src/audit-log/tests/audit-log.test.ts +++ b/src/audit-log/tests/audit-log.test.ts @@ -1,7 +1,6 @@ import { AuditLogService } from '../audit-log.service'; import { Repository } from 'typeorm'; import { AuditLog } from '../audit-log.entity'; -import { getRepositoryToken } from '@nestjs/typeorm'; describe('AuditLogService', () => { let service: AuditLogService; diff --git a/src/backup/backup.controller.ts b/src/backup/backup.controller.ts index 6b36f4f8..c71a0ed5 100644 --- a/src/backup/backup.controller.ts +++ b/src/backup/backup.controller.ts @@ -4,7 +4,6 @@ import { Get, Param, Body, - UseGuards, ParseUUIDPipe, HttpCode, HttpStatus, diff --git a/src/backup/backup.service.ts b/src/backup/backup.service.ts index 6ae7a973..a159875d 100644 --- a/src/backup/backup.service.ts +++ b/src/backup/backup.service.ts @@ -4,7 +4,7 @@ import { Repository, LessThan } from 'typeorm'; import { InjectQueue } from '@nestjs/bull'; import { Queue } from 'bull'; import { ConfigService } from '@nestjs/config'; -import { Cron, CronExpression } from '@nestjs/schedule'; +import { Cron } from '@nestjs/schedule'; import { BackupRecord } from './entities/backup-record.entity'; import { BackupStatus } from './enums/backup-status.enum'; import { BackupType } from './enums/backup-type.enum'; diff --git a/src/backup/processing/backup-queue.processor.ts b/src/backup/processing/backup-queue.processor.ts index 2ce65466..aee17f48 100644 --- a/src/backup/processing/backup-queue.processor.ts +++ b/src/backup/processing/backup-queue.processor.ts @@ -18,7 +18,7 @@ import { exec } from 'child_process'; import { promisify } from 'util'; import * as fs from 'fs'; import * as path from 'path'; -import { KMSClient, EncryptCommand, DecryptCommand } from '@aws-sdk/client-kms'; +import { KMSClient, EncryptCommand } from '@aws-sdk/client-kms'; import { S3Client, CopyObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3'; const execAsync = promisify(exec); diff --git a/src/cdn/caching/edge-caching.service.ts b/src/cdn/caching/edge-caching.service.ts index d210dac5..75da8061 100644 --- a/src/cdn/caching/edge-caching.service.ts +++ b/src/cdn/caching/edge-caching.service.ts @@ -24,7 +24,7 @@ export class EdgeCachingService { async getEdgeUrl(originalUrl: string, location?: string): Promise { // In a real implementation, this would return the CDN URL for the optimal edge location // For now, just return the original URL with CDN prefix - const cdnUrl = originalUrl.replace(/^https?:\/\/[^\/]+/, 'https://cdn.example.com'); + const cdnUrl = originalUrl.replace(/^https?:\/\/[^/]+/, 'https://cdn.example.com'); // Add location-based routing if needed if (location) { diff --git a/src/cdn/cdn.controller.ts b/src/cdn/cdn.controller.ts index f541dcc0..1d919773 100644 --- a/src/cdn/cdn.controller.ts +++ b/src/cdn/cdn.controller.ts @@ -151,6 +151,7 @@ export class CdnController { timestamp: new Date().toISOString(), }; } catch (error) { + console.error('health check failed'); throw new HttpException('Health check failed', HttpStatus.INTERNAL_SERVER_ERROR); } } @@ -182,6 +183,7 @@ export class CdnController { }, }; } catch (error) { + console.error('failed to retrieve'); throw new HttpException('Failed to retrieve analytics', HttpStatus.INTERNAL_SERVER_ERROR); } } diff --git a/src/cdn/cdn.service.ts b/src/cdn/cdn.service.ts index 342ec531..38b0a4d3 100644 --- a/src/cdn/cdn.service.ts +++ b/src/cdn/cdn.service.ts @@ -7,7 +7,6 @@ import { AssetOptimizationService } from './optimization/asset-optimization.serv import { EdgeCachingService } from './caching/edge-caching.service'; import { GeoLocationService } from './geo/geo-location.service'; import { CloudflareService } from './providers/cloudflare.service'; -import { AWSCloudFrontService } from './providers/aws-cloudfront.service'; import { ContentMetadata, ContentType, ContentStatus } from './entities/content-metadata.entity'; export interface ContentDeliveryOptions { diff --git a/src/cdn/dto/upload-content.dto.ts b/src/cdn/dto/upload-content.dto.ts index 159da2e7..459932f9 100644 --- a/src/cdn/dto/upload-content.dto.ts +++ b/src/cdn/dto/upload-content.dto.ts @@ -1,4 +1,4 @@ -import { IsOptional, IsString, IsNumber, IsBoolean, IsEnum, Min, Max } from 'class-validator'; +import { IsOptional, IsString, IsNumber, IsBoolean, Min, Max } from 'class-validator'; import { ApiPropertyOptional } from '@nestjs/swagger'; export class UploadContentDto { diff --git a/src/cdn/providers/aws-cloudfront.service.ts b/src/cdn/providers/aws-cloudfront.service.ts index d0c5a563..6f801253 100644 --- a/src/cdn/providers/aws-cloudfront.service.ts +++ b/src/cdn/providers/aws-cloudfront.service.ts @@ -5,8 +5,6 @@ import { CloudFrontClient, CreateInvalidationCommand, GetInvalidationCommand, - CreateDistributionCommand, - UpdateDistributionCommand, } from '@aws-sdk/client-cloudfront'; import { S3Client, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3'; @@ -135,7 +133,7 @@ export class AWSCloudFrontService { const result = await this.cloudfrontClient.send(command); // Wait for invalidation to complete - await this.waitForInvalidation(result.Invalidation?.Id!); + await this.waitForInvalidation(result.Invalidation?.Id || ''); return { success: true, @@ -170,7 +168,7 @@ export class AWSCloudFrontService { const result = await this.cloudfrontClient.send(command); - await this.waitForInvalidation(result.Invalidation?.Id!); + await this.waitForInvalidation(result.Invalidation?.Id || ''); return { success: true, diff --git a/src/collaboration/collaboration.controller.ts b/src/collaboration/collaboration.controller.ts index 0c6d6d9d..99326bce 100644 --- a/src/collaboration/collaboration.controller.ts +++ b/src/collaboration/collaboration.controller.ts @@ -6,18 +6,19 @@ import { Delete, Body, Param, - Query, UseGuards, Request, } from '@nestjs/common'; import { CollaborationService } from './collaboration.service'; -import { SharedDocumentService, CollaborativeDocument } from './documents/shared-document.service'; -import { WhiteboardService, CollaborativeWhiteboard } from './whiteboard/whiteboard.service'; +import { SharedDocumentService } from './documents/shared-document.service'; +import { WhiteboardService } from './whiteboard/whiteboard.service'; import { VersionControlService } from './versioning/version-control.service'; -import { CollaborationPermissionsService } from './permissions/collaboration-permissions.service'; +import { + CollaborationPermissionsService, + PermissionLevel, +} from './permissions/collaboration-permissions.service'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { RolesGuard } from '../auth/guards/roles.guard'; -import { PermissionLevel } from './permissions/collaboration-permissions.service'; @Controller('collaboration') @UseGuards(JwtAuthGuard, RolesGuard) diff --git a/src/common/constants/app.constants.ts b/src/common/constants/app.constants.ts new file mode 100644 index 00000000..b1a4858a --- /dev/null +++ b/src/common/constants/app.constants.ts @@ -0,0 +1,33 @@ +/** + * Application constants + * Centralized location for magic values and configuration constants + */ + +export const APP_CONSTANTS = { + // Security constants + DUMMY_USER_ID: '00000000-0000-0000-0000-000000000000', + + // Pagination defaults + DEFAULT_PAGE_SIZE: 10, + MAX_PAGE_SIZE: 100, + + // Status values + COURSE_STATUS: { + DRAFT: 'draft', + PUBLISHED: 'published', + ARCHIVED: 'archived', + }, + + ENROLLMENT_STATUS: { + ACTIVE: 'active', + COMPLETED: 'completed', + CANCELLED: 'cancelled', + }, + + // Role constants + USER_ROLES: { + INSTRUCTOR: 'instructor', + STUDENT: 'student', + ADMIN: 'admin', + }, +} as const; diff --git a/src/common/interceptors/logging.interceptor.ts b/src/common/interceptors/logging.interceptor.ts index 5af3c4b8..21b75b7b 100644 --- a/src/common/interceptors/logging.interceptor.ts +++ b/src/common/interceptors/logging.interceptor.ts @@ -1,7 +1,6 @@ import { Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger } from '@nestjs/common'; -import { Observable } from 'rxjs'; +import { Observable, throwError } from 'rxjs'; import { tap, catchError } from 'rxjs/operators'; -import { throwError } from 'rxjs'; import { Request, Response } from 'express'; export interface RequestLog { @@ -97,11 +96,13 @@ export class LoggingInterceptor implements NestInterceptor { private logIncoming(log: RequestLog): void { const message = `→ ${log.method} ${log.url}`; - this.isProd - ? this.logger.log(JSON.stringify({ event: 'request.incoming', ...log })) - : this.logger.log( - `${message} | id=${log.requestId} ip=${log.ip}${log.userId ? ` user=${log.userId}` : ''}`, - ); + if (this.isProd) { + this.logger.log(JSON.stringify({ event: 'request.incoming', ...log })); + } else { + this.logger.log( + `${message} | id=${log.requestId} ip=${log.ip}${log.userId ? ` user=${log.userId}` : ''}`, + ); + } } private logOutgoing(log: ResponseLog): void { diff --git a/src/courses/courses.controller.ts b/src/courses/courses.controller.ts index c6604387..6239bd0e 100644 --- a/src/courses/courses.controller.ts +++ b/src/courses/courses.controller.ts @@ -1,4 +1,15 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from '@nestjs/common'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, + Query, + UseGuards, + Request, +} from '@nestjs/common'; import { CoursesService } from './courses.service'; import { CreateCourseDto } from './dto/create-course.dto'; import { UpdateCourseDto } from './dto/update-course.dto'; @@ -8,6 +19,7 @@ import { CreateModuleDto } from './dto/create-module.dto'; import { LessonsService } from './lessons/lessons.service'; import { CreateLessonDto } from './dto/create-lesson.dto'; import { EnrollmentsService } from './enrollments/enrollments.service'; +import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; @Controller('courses') export class CoursesController { @@ -19,12 +31,13 @@ export class CoursesController { ) {} @Post() - create(@Body() createCourseDto: CreateCourseDto) { - // In a real app, user comes from req.user (JWT) - // For now, we'll assume a user is passed or we create a dummy one in service if needed - // But service expects User entity. - // We'll mock it here for simplicity of the API implementation task - const user = { id: '00000000-0000-0000-0000-000000000000' } as any; + @UseGuards(JwtAuthGuard) + create(@Request() req, @Body() createCourseDto: CreateCourseDto) { + // Get user from JWT token + const user = req.user; + if (!user || !user.id) { + throw new Error('User not authenticated'); + } return this.coursesService.create({ ...createCourseDto, instructorId: user.id, @@ -37,7 +50,8 @@ export class CoursesController { } @Get('analytics') - getAnalytics() { + @UseGuards(JwtAuthGuard) + getAnalytics(@Request() req) { return this.coursesService.getAnalytics(); } @@ -47,33 +61,49 @@ export class CoursesController { } @Patch(':id') + @UseGuards(JwtAuthGuard) update(@Param('id') id: string, @Body() updateCourseDto: UpdateCourseDto) { return this.coursesService.update(id, updateCourseDto); } @Delete(':id') + @UseGuards(JwtAuthGuard) remove(@Param('id') id: string) { return this.coursesService.remove(id); } // Modules @Post(':id/modules') - createModule(@Param('id') courseId: string, @Body() createModuleDto: CreateModuleDto) { + @UseGuards(JwtAuthGuard) + createModule( + @Request() req, + @Param('id') courseId: string, + @Body() createModuleDto: CreateModuleDto, + ) { createModuleDto.courseId = courseId; return this.modulesService.create(createModuleDto); } // Lessons @Post('modules/:moduleId/lessons') - createLesson(@Param('moduleId') moduleId: string, @Body() createLessonDto: CreateLessonDto) { + @UseGuards(JwtAuthGuard) + createLesson( + @Request() req, + @Param('moduleId') moduleId: string, + @Body() createLessonDto: CreateLessonDto, + ) { createLessonDto.moduleId = moduleId; return this.lessonsService.create(createLessonDto); } // Enrollments @Post(':id/enroll') - enroll(@Param('id') courseId: string) { - const userId = '00000000-0000-0000-0000-000000000000'; // Placeholder + @UseGuards(JwtAuthGuard) + enroll(@Request() req, @Param('id') courseId: string) { + const userId = req.user.id; + if (!userId) { + throw new Error('User not authenticated'); + } return this.enrollmentsService.enroll(userId, courseId); } } diff --git a/src/courses/dto/update-course.dto.ts b/src/courses/dto/update-course.dto.ts index ef560a3e..28f8c93c 100644 --- a/src/courses/dto/update-course.dto.ts +++ b/src/courses/dto/update-course.dto.ts @@ -1,7 +1,6 @@ -import { PartialType } from '@nestjs/swagger'; import { CreateCourseDto } from './create-course.dto'; +import { PartialType, ApiPropertyOptional } from '@nestjs/swagger'; import { IsString, IsOptional, IsEnum } from 'class-validator'; -import { ApiPropertyOptional } from '@nestjs/swagger'; export class UpdateCourseDto extends PartialType(CreateCourseDto) { @ApiPropertyOptional({ enum: ['draft', 'published', 'archived'] }) diff --git a/src/data-warehouse/loading/incremental-loader.service.ts b/src/data-warehouse/loading/incremental-loader.service.ts index 5ac05752..0399c861 100644 --- a/src/data-warehouse/loading/incremental-loader.service.ts +++ b/src/data-warehouse/loading/incremental-loader.service.ts @@ -134,34 +134,38 @@ export class IncrementalLoaderService { let recordsDeleted = 0; switch (job.config.loadType) { - case 'timestamp': + case 'timestamp': { const timestampResult = await this.loadByTimestamp(job); recordsProcessed = timestampResult.processed; recordsInserted = timestampResult.inserted; recordsUpdated = timestampResult.updated; break; + } - case 'sequence': + case 'sequence': { const sequenceResult = await this.loadBySequence(job); recordsProcessed = sequenceResult.processed; recordsInserted = sequenceResult.inserted; recordsUpdated = sequenceResult.updated; break; + } - case 'watermark': + case 'watermark': { const watermarkResult = await this.loadByWatermark(job); recordsProcessed = watermarkResult.processed; recordsInserted = watermarkResult.inserted; recordsUpdated = watermarkResult.updated; break; + } - case 'cdc': + case 'cdc': { const cdcResult = await this.loadByCDC(job); recordsProcessed = cdcResult.processed; recordsInserted = cdcResult.inserted; recordsUpdated = cdcResult.updated; recordsDeleted = cdcResult.deleted; break; + } } job.status = 'completed'; diff --git a/src/data-warehouse/quality/data-quality.service.ts b/src/data-warehouse/quality/data-quality.service.ts index eecffb9a..7a9929cf 100644 --- a/src/data-warehouse/quality/data-quality.service.ts +++ b/src/data-warehouse/quality/data-quality.service.ts @@ -506,11 +506,12 @@ export class DataQualityService { return value !== '' && value !== null && value !== undefined; case 'valid email format': return typeof value === 'string' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value); - case 'within last 5 years': + case 'within last 5 years': { const date = new Date(value); const fiveYearsAgo = new Date(); fiveYearsAgo.setFullYear(fiveYearsAgo.getFullYear() - 5); return date >= fiveYearsAgo; + } default: return true; } diff --git a/src/rate-limiting/rate-limiting.controller.spec.ts b/src/rate-limiting/rate-limiting.controller.spec.ts index 77dc8537..1040ae69 100644 --- a/src/rate-limiting/rate-limiting.controller.spec.ts +++ b/src/rate-limiting/rate-limiting.controller.spec.ts @@ -1,6 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { RateLimitingController } from './rate-limiting.controller'; import { RateLimitingService } from './rate-limiting.service'; +import { ThrottlingService } from './services/throttling.service'; describe('RateLimitingController', () => { let controller: RateLimitingController; @@ -8,7 +9,15 @@ describe('RateLimitingController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [RateLimitingController], - providers: [RateLimitingService], + providers: [ + RateLimitingService, + { + provide: ThrottlingService, + useValue: { + checkLimit: jest.fn(), + }, + }, + ], }).compile(); controller = module.get(RateLimitingController); diff --git a/src/rate-limiting/rate-limiting.controller.ts b/src/rate-limiting/rate-limiting.controller.ts index 9dd1f6f8..fcee8a74 100644 --- a/src/rate-limiting/rate-limiting.controller.ts +++ b/src/rate-limiting/rate-limiting.controller.ts @@ -3,7 +3,7 @@ import { RateLimitingService } from './rate-limiting.service'; import { RateLimitGuard } from './services/limit-guard/guard'; import { CreateRateLimitingDto } from './dto/create-rate-limiting.dto'; import { UpdateRateLimitingDto } from './dto/update-rate-limiting.dto'; -import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard'; +import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; @Controller('rate-limiting') export class RateLimitingController { diff --git a/src/rate-limiting/services/limit-guard/guard.ts b/src/rate-limiting/services/limit-guard/guard.ts index d85bf99e..7bea66f6 100644 --- a/src/rate-limiting/services/limit-guard/guard.ts +++ b/src/rate-limiting/services/limit-guard/guard.ts @@ -1,5 +1,5 @@ import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; -import { RateLimitingService } from 'src/rate-limiting/rate-limiting.service'; +import { RateLimitingService } from '../../rate-limiting.service'; @Injectable() export class RateLimitGuard implements CanActivate { diff --git a/src/users/entities/user.entity.ts b/src/users/entities/user.entity.ts index 6850d615..115ed282 100644 --- a/src/users/entities/user.entity.ts +++ b/src/users/entities/user.entity.ts @@ -7,8 +7,8 @@ import { Index, OneToMany, } from 'typeorm'; -import { Course } from 'src/courses/entities/course.entity'; -import { Enrollment } from 'src/courses/entities/enrollment.entity'; +import { Course } from '../../courses/entities/course.entity'; +import { Enrollment } from '../../courses/entities/enrollment.entity'; export enum UserRole { STUDENT = 'student', diff --git a/test/utils/check-coverage-summary.js b/test/utils/check-coverage-summary.js index d258a6bc..c8618ed0 100644 --- a/test/utils/check-coverage-summary.js +++ b/test/utils/check-coverage-summary.js @@ -1,5 +1,9 @@ -const fs = require('fs'); -const path = require('path'); +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); const summaryPath = path.resolve(process.cwd(), 'coverage/coverage-summary.json'); @@ -32,9 +36,7 @@ for (const metric of metrics) { if (failed.length > 0) { console.error('Coverage threshold check failed:'); for (const { metric, actual, expected } of failed) { - console.error( - ` - ${metric}: ${actual.toFixed(2)}% is below required ${expected}%`, - ); + console.error(` - ${metric}: ${actual.toFixed(2)}% is below required ${expected}%`); } process.exit(1); }