diff --git a/angular.json b/angular.json index c74d9fe..a6f9ac3 100644 --- a/angular.json +++ b/angular.json @@ -40,6 +40,10 @@ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.production.ts" + }, + { + "replace": "src/app/interceptors/mock-data.interceptor.ts", + "with": "src/app/interceptors/mock-data.interceptor.production.ts" } ], "styles": [ @@ -49,7 +53,7 @@ "budgets": [ { "type": "initial", - "maximumWarning": "500kB", + "maximumWarning": "600kB", "maximumError": "1MB" }, { @@ -92,6 +96,10 @@ { "replace": "src/app/brands/brand-routes.ts", "with": "src/app/brands/brand-routes.novo.ts" + }, + { + "replace": "src/app/interceptors/mock-data.interceptor.ts", + "with": "src/app/interceptors/mock-data.interceptor.production.ts" } ], "index": "src/index.novo.html", @@ -124,7 +132,7 @@ "budgets": [ { "type": "initial", - "maximumWarning": "500kB", + "maximumWarning": "600kB", "maximumError": "1MB" }, { @@ -158,6 +166,10 @@ { "replace": "src/app/brands/brand-routes.ts", "with": "src/app/brands/brand-routes.lavero.ts" + }, + { + "replace": "src/app/interceptors/mock-data.interceptor.ts", + "with": "src/app/interceptors/mock-data.interceptor.production.ts" } ], "index": "src/index.lavero.html", @@ -190,7 +202,7 @@ "budgets": [ { "type": "initial", - "maximumWarning": "500kB", + "maximumWarning": "600kB", "maximumError": "1MB" }, { diff --git a/package-lock.json b/package-lock.json index fb13356..52b12ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,9 +14,7 @@ "@angular/compiler": "21.1.5", "@angular/core": "21.1.5", "@angular/forms": "21.1.5", - "@angular/material": "21.1.5", "@angular/platform-browser": "21.1.5", - "@angular/platform-browser-dynamic": "21.1.5", "@angular/router": "21.1.5", "@angular/service-worker": "21.1.5", "primeicons": "^7.0.0", @@ -29,13 +27,6 @@ "@angular/build": "21.1.5", "@angular/cli": "21.1.5", "@angular/compiler-cli": "21.1.5", - "@types/jasmine": "~5.1.0", - "jasmine-core": "~5.13.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", "typescript": "~5.9.3" } }, @@ -556,36 +547,6 @@ } } }, - "node_modules/@angular/compiler-cli/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular/compiler-cli/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular/core": { "version": "21.1.5", "resolved": "https://registry.npmjs.org/@angular/core/-/core-21.1.5.tgz", @@ -630,23 +591,6 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@angular/material": { - "version": "21.1.5", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-21.1.5.tgz", - "integrity": "sha512-D6JvFulPvIKhPJ52prMV7DxwYMzcUpHar11ZcMb7r9WQzUfCS3FDPXfMAce5n3h+3kFccfmmGpnyBwqTlLPSig==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/cdk": "21.1.5", - "@angular/common": "^21.0.0 || ^22.0.0", - "@angular/core": "^21.0.0 || ^22.0.0", - "@angular/forms": "^21.0.0 || ^22.0.0", - "@angular/platform-browser": "^21.0.0 || ^22.0.0", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, "node_modules/@angular/platform-browser": { "version": "21.1.5", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.1.5.tgz", @@ -669,24 +613,6 @@ } } }, - "node_modules/@angular/platform-browser-dynamic": { - "version": "21.1.5", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-21.1.5.tgz", - "integrity": "sha512-Pd8nPbJSIONnze1WS9wLBAtaFw4TYIH+ZGjKHS9G1E9l09tDWtHWyB7dY82Sc//Nc8iR4V7dcsbUmFjOJHThww==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/common": "21.1.5", - "@angular/compiler": "21.1.5", - "@angular/core": "21.1.5", - "@angular/platform-browser": "21.1.5" - } - }, "node_modules/@angular/router": { "version": "21.1.5", "resolved": "https://registry.npmjs.org/@angular/router/-/router-21.1.5.tgz", @@ -1023,6 +949,8 @@ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.1.90" } @@ -3861,7 +3789,9 @@ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/@standard-schema/spec": { "version": "1.1.0", @@ -3926,6 +3856,8 @@ "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@types/node": "*" } @@ -3937,19 +3869,14 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/jasmine": { - "version": "5.1.13", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-5.1.13.tgz", - "integrity": "sha512-MYCcDkruFc92LeYZux5BC0dmqo2jk+M5UIZ4/oFnAPCXN9mCcQhLyj7F3/Za7rocVyt5YRr1MmqJqFlvQ9LVcg==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "25.0.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.1.tgz", "integrity": "sha512-czWPzKIAXucn9PtsttxmumiQ9N0ok9FrBwgRWrwmVLlp86BrMExzvXRLFYRJ+Ex3g6yqj+KuaxfX1JTgV2lpfg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -4117,6 +4044,8 @@ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -4131,6 +4060,8 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8.6" }, @@ -4143,7 +4074,9 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/base64id": { "version": "2.0.0", @@ -4151,6 +4084,8 @@ "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": "^4.5.0 || >= 5.9" } @@ -4191,6 +4126,8 @@ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8" }, @@ -4266,6 +4203,8 @@ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4277,6 +4216,8 @@ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -4475,16 +4416,16 @@ "license": "MIT" }, "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" + "readdirp": "^5.0.0" }, "engines": { - "node": ">= 14.16.0" + "node": ">= 20.19.0" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -4638,7 +4579,9 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/connect": { "version": "3.7.0", @@ -4646,6 +4589,8 @@ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", @@ -4662,6 +4607,8 @@ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ms": "2.0.0" } @@ -4672,6 +4619,8 @@ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.8" } @@ -4682,6 +4631,8 @@ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -4700,7 +4651,9 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/connect/node_modules/on-finished": { "version": "2.3.0", @@ -4708,6 +4661,8 @@ "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ee-first": "1.1.1" }, @@ -4721,6 +4676,8 @@ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -4840,7 +4797,9 @@ "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/date-format": { "version": "4.0.14", @@ -4848,6 +4807,8 @@ "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=4.0" } @@ -4886,6 +4847,8 @@ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -4907,7 +4870,9 @@ "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/dom-serialize": { "version": "2.2.1", @@ -4915,6 +4880,8 @@ "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "custom-event": "~1.0.0", "ent": "~2.2.0", @@ -5058,6 +5025,8 @@ "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", @@ -5079,6 +5048,8 @@ "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=10.0.0" } @@ -5089,6 +5060,8 @@ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -5103,6 +5076,8 @@ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -5121,6 +5096,8 @@ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -5131,6 +5108,8 @@ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -5144,6 +5123,8 @@ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -5154,6 +5135,8 @@ "integrity": "sha512-kKvD1tO6BM+oK9HzCPpUdRb4vKFQY/FPTFmurMvh6LlN68VMrdj77w8yp51/kDbpkFOS9J8w5W6zIzgM2H8/hw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -5314,7 +5297,9 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/eventsource": { "version": "3.0.7", @@ -5414,7 +5399,9 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -5464,6 +5451,8 @@ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -5498,7 +5487,9 @@ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, - "license": "ISC" + "license": "ISC", + "optional": true, + "peer": true }, "node_modules/follow-redirects": { "version": "1.15.11", @@ -5512,6 +5503,8 @@ } ], "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=4.0" }, @@ -5547,6 +5540,8 @@ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -5574,7 +5569,9 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true, - "license": "ISC" + "license": "ISC", + "optional": true, + "peer": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -5680,6 +5677,8 @@ "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5701,6 +5700,8 @@ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -5735,16 +5736,6 @@ "dev": true, "license": "ISC" }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -5764,6 +5755,8 @@ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -5820,13 +5813,6 @@ "node": "20 || >=22" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, "node_modules/htmlparser2": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", @@ -5894,6 +5880,8 @@ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -6001,6 +5989,8 @@ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -6049,6 +6039,8 @@ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -6078,6 +6070,7 @@ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", + "optional": true, "engines": { "node": ">=0.10.0" } @@ -6104,6 +6097,7 @@ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -6130,6 +6124,8 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.12.0" } @@ -6147,6 +6143,8 @@ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", @@ -6179,6 +6177,8 @@ "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 8.0.0" }, @@ -6220,67 +6220,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jasmine-core": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.13.0.tgz", - "integrity": "sha512-vsYjfh7lyqvZX5QgqKc4YH8phs7g96Z8bsdIFNEU3VqXhlHaq+vov/Fgn/sr6MiUczdZkyXRC3TX369Ll4Nzbw==", - "dev": true, - "license": "MIT" - }, "node_modules/jose": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.3.tgz", @@ -6361,6 +6300,8 @@ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -6381,6 +6322,8 @@ "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@colors/colors": "1.5.0", "body-parser": "^1.19.0", @@ -6414,115 +6357,14 @@ "node": ">= 10" } }, - "node_modules/karma-chrome-launcher": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz", - "integrity": "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "which": "^1.2.1" - } - }, - "node_modules/karma-chrome-launcher/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/karma-coverage": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.1.tgz", - "integrity": "sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.0.5", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/karma-coverage/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/karma-coverage/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/karma-jasmine": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", - "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "jasmine-core": "^4.1.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "karma": "^6.0.0" - } - }, - "node_modules/karma-jasmine-html-reporter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.1.0.tgz", - "integrity": "sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "jasmine-core": "^4.0.0 || ^5.0.0", - "karma": "^6.0.0", - "karma-jasmine": "^5.0.0" - } - }, - "node_modules/karma-jasmine/node_modules/jasmine-core": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.1.tgz", - "integrity": "sha512-VYz/BjjmC3klLJlLwA4Kw8ytk0zDSmbbDLNs794VnWmkcCB7I9aAL/D48VNQtmITyPvea2C3jdUMfc3kAoy0PQ==", - "dev": true, - "license": "MIT" - }, "node_modules/karma/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -6533,6 +6375,8 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -6549,6 +6393,8 @@ "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", @@ -6574,6 +6420,8 @@ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -6599,6 +6447,8 @@ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -6611,6 +6461,8 @@ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ms": "2.0.0" } @@ -6620,7 +6472,9 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/karma/node_modules/iconv-lite": { "version": "0.4.24", @@ -6628,6 +6482,8 @@ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -6641,6 +6497,8 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -6651,6 +6509,8 @@ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -6661,6 +6521,8 @@ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -6671,6 +6533,8 @@ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -6683,7 +6547,9 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/karma/node_modules/picomatch": { "version": "2.3.1", @@ -6691,6 +6557,8 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8.6" }, @@ -6704,6 +6572,8 @@ "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", @@ -6720,6 +6590,8 @@ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -6733,6 +6605,8 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -6743,6 +6617,8 @@ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6758,6 +6634,8 @@ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -6771,6 +6649,8 @@ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -6785,6 +6665,8 @@ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -6803,6 +6685,8 @@ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -6822,6 +6706,8 @@ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "engines": { "node": ">=10" } @@ -6902,7 +6788,9 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/log-symbols": { "version": "7.0.1", @@ -6965,6 +6853,8 @@ "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", "dev": true, "license": "Apache-2.0", + "optional": true, + "peer": true, "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", @@ -6996,22 +6886,6 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/make-fetch-happen": { "version": "15.0.3", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz", @@ -7074,6 +6948,8 @@ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "bin": { "mime": "cli.js" }, @@ -7127,6 +7003,8 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -7140,6 +7018,8 @@ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7303,6 +7183,8 @@ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -7504,6 +7386,8 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -7860,6 +7744,8 @@ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8069,7 +7955,9 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/qjobs": { "version": "1.2.0", @@ -8077,6 +7965,8 @@ "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.9" } @@ -8124,13 +8014,13 @@ } }, "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 14.18.0" + "node": ">= 20.19.0" }, "funding": { "type": "individual", @@ -8150,6 +8040,8 @@ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8169,7 +8061,9 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/resolve": { "version": "1.22.11", @@ -8233,6 +8127,8 @@ "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -8352,6 +8248,8 @@ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -8392,6 +8290,36 @@ "@parcel/watcher": "^2.4.1" } }, + "node_modules/sass/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -8623,6 +8551,8 @@ "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -8642,6 +8572,8 @@ "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "debug": "~4.3.4", "ws": "~8.17.1" @@ -8653,6 +8585,8 @@ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -8671,6 +8605,8 @@ "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -8685,6 +8621,8 @@ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -8703,6 +8641,8 @@ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -8717,6 +8657,8 @@ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -8735,6 +8677,8 @@ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -8745,6 +8689,8 @@ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -8758,6 +8704,8 @@ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -8911,6 +8859,8 @@ "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", @@ -8954,19 +8904,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -9030,6 +8967,8 @@ "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=14.14" } @@ -9040,6 +8979,8 @@ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "is-number": "^7.0.0" }, @@ -9145,6 +9086,8 @@ } ], "license": "MIT", + "optional": true, + "peer": true, "bin": { "ua-parser-js": "script/cli.js" }, @@ -9167,7 +9110,9 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/unique-filename": { "version": "5.0.0", @@ -9201,6 +9146,8 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 4.0.0" } @@ -9252,6 +9199,8 @@ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 0.4.0" } @@ -9368,6 +9317,8 @@ "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -9509,6 +9460,8 @@ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index ad79ed2..bf8c052 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "build:dexar": "ng build --configuration=production", "build:novo": "ng build --configuration=novo-production", "watch": "ng build --watch --configuration development", - "test": "ng test", "lavero": "ng serve --configuration=lavero --port 4202 --proxy-config proxy.conf.lavero.json", "start:lavero": "ng serve --configuration=lavero --port 4202", "build:lavero": "ng build --configuration=lavero-production" @@ -25,9 +24,7 @@ "@angular/compiler": "21.1.5", "@angular/core": "21.1.5", "@angular/forms": "21.1.5", - "@angular/material": "21.1.5", "@angular/platform-browser": "21.1.5", - "@angular/platform-browser-dynamic": "21.1.5", "@angular/router": "21.1.5", "@angular/service-worker": "21.1.5", "primeicons": "^7.0.0", @@ -40,13 +37,6 @@ "@angular/build": "21.1.5", "@angular/cli": "21.1.5", "@angular/compiler-cli": "21.1.5", - "@types/jasmine": "~5.1.0", - "jasmine-core": "~5.13.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", "typescript": "~5.9.3" } -} \ No newline at end of file +} diff --git a/src/app/app.html b/src/app/app.html index 90c613a..e0926f0 100644 --- a/src/app/app.html +++ b/src/app/app.html @@ -18,6 +18,10 @@ } - + @defer (on viewport) { + + } @placeholder { + + } } \ No newline at end of file diff --git a/src/app/app.scss b/src/app/app.scss index 31f32ec..e01dd8c 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -5,6 +5,10 @@ flex-direction: column; } +.footer-placeholder { + min-height: 1px; +} + .server-check-overlay, .server-error-overlay { display: flex; diff --git a/src/app/app.ts b/src/app/app.ts index ef63784..9a1bf06 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -2,10 +2,10 @@ import { Component, OnInit, signal, ApplicationRef, inject, DestroyRef } from '@angular/core'; import { Router, RouterOutlet, NavigationEnd } from '@angular/router'; import { Title } from '@angular/platform-browser'; +import { HttpClient } from '@angular/common/http'; import { HeaderComponent } from './components/header/header.component'; import { FooterComponent } from './components/footer/footer.component'; import { BackButtonComponent } from './components/back-button/back-button.component'; -import { ApiService } from './services'; import { interval, concat } from 'rxjs'; import { filter, first } from 'rxjs/operators'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @@ -27,7 +27,7 @@ export class App implements OnInit { serverAvailable = signal(false); private destroyRef = inject(DestroyRef); - private apiService = inject(ApiService); + private http = inject(HttpClient); private titleService = inject(Title); private swUpdate = inject(SwUpdate); private appRef = inject(ApplicationRef); @@ -55,7 +55,7 @@ export class App implements OnInit { private checkServerHealth(): void { this.checkingServer.set(true); - this.apiService.ping() + this.http.get<{ message: string }>(`${environment.apiUrl}/ping`) .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe({ next: () => { diff --git a/src/app/components/header/header.component.ts b/src/app/components/header/header.component.ts index e909d3f..2f4d528 100644 --- a/src/app/components/header/header.component.ts +++ b/src/app/components/header/header.component.ts @@ -1,6 +1,7 @@ import { Component, ChangeDetectionStrategy, Renderer2, inject, DOCUMENT } from '@angular/core'; import { Router, RouterLink, RouterLinkActive } from '@angular/router'; -import { CartService, LanguageService } from '../../services'; +import { CartService } from '../../services/cart.service'; +import { LanguageService } from '../../services/language.service'; import { environment } from '../../../environments/environment'; import { LogoComponent } from '../logo/logo.component'; import { LanguageSelectorComponent } from '../language-selector/language-selector.component'; diff --git a/src/app/components/telegram-login/telegram-login.component.ts b/src/app/components/telegram-login/telegram-login.component.ts index ec5c078..f1ee79e 100644 --- a/src/app/components/telegram-login/telegram-login.component.ts +++ b/src/app/components/telegram-login/telegram-login.component.ts @@ -23,7 +23,6 @@ export class TelegramLoginComponent implements OnDestroy { private readonly pollIntervalMs = 5000; private pollTimer?: ReturnType; - private telegramFallbackTimer?: ReturnType; private readonly handleVisibilityChange = () => { if (typeof document !== 'undefined' && document.visibilityState === 'visible') { this.checkLoginAfterReturn(); diff --git a/src/app/config/constants.ts b/src/app/config/constants.ts index 7ad10bd..2359bd9 100644 --- a/src/app/config/constants.ts +++ b/src/app/config/constants.ts @@ -2,7 +2,6 @@ export const PAYMENT_POLL_INTERVAL_MS = 5000; export const PAYMENT_MAX_CHECKS = 36; export const PAYMENT_TIMEOUT_CLOSE_MS = 3000; -export const PAYMENT_ERROR_CLOSE_MS = 4000; export const LINK_COPIED_DURATION_MS = 2000; // Infinite scroll @@ -12,7 +11,6 @@ export const ITEMS_PER_PAGE = 50; // Search export const SEARCH_DEBOUNCE_MS = 300; -export const SEARCH_MIN_LENGTH = 3; // Cache export const CACHE_DURATION_MS = 5 * 60 * 1000; diff --git a/src/app/interceptors/cache.interceptor.ts b/src/app/interceptors/cache.interceptor.ts index 57ee03e..65b7cc4 100644 --- a/src/app/interceptors/cache.interceptor.ts +++ b/src/app/interceptors/cache.interceptor.ts @@ -50,11 +50,6 @@ export const cacheInterceptor: HttpInterceptorFn = (req, next) => { ); }; -/** Clear all cached responses */ -export function clearCache(): void { - cache.clear(); -} - function cleanupExpiredCache(): void { const now = Date.now(); for (const [url, data] of cache.entries()) { diff --git a/src/app/interceptors/mock-data.interceptor.production.ts b/src/app/interceptors/mock-data.interceptor.production.ts new file mode 100644 index 0000000..e181464 --- /dev/null +++ b/src/app/interceptors/mock-data.interceptor.production.ts @@ -0,0 +1,3 @@ +import { HttpInterceptorFn } from '@angular/common/http'; + +export const mockDataInterceptor: HttpInterceptorFn = (req, next) => next(req); diff --git a/src/app/models/auth.model.ts b/src/app/models/auth.model.ts index 111d06b..9f8a713 100644 --- a/src/app/models/auth.model.ts +++ b/src/app/models/auth.model.ts @@ -12,14 +12,4 @@ export interface WebSessionStart { url: string; } -export interface TelegramAuthData { - id: number; - first_name: string; - last_name?: string; - username?: string; - photo_url?: string; - auth_date: number; - hash: string; -} - export type AuthStatus = 'unknown' | 'checking' | 'authenticated' | 'expired' | 'unauthenticated'; diff --git a/src/app/models/category.model.ts b/src/app/models/category.model.ts index cc3f9d0..38c34d6 100644 --- a/src/app/models/category.model.ts +++ b/src/app/models/category.model.ts @@ -33,6 +33,6 @@ export interface Subcategory { subcategories?: Subcategory[]; } -export interface CategoryTranslation { +interface CategoryTranslation { name?: string; } diff --git a/src/app/models/item.model.ts b/src/app/models/item.model.ts index e54d459..9365fc0 100644 --- a/src/app/models/item.model.ts +++ b/src/app/models/item.model.ts @@ -1,4 +1,4 @@ -export interface Photo { +interface Photo { photo?: string; video?: string; url: string; @@ -10,7 +10,7 @@ export interface DescriptionField { value: string; } -export interface Comment { +interface Comment { id?: string; text: string; author?: string; @@ -18,13 +18,13 @@ export interface Comment { createdAt?: string; } -export interface ItemTranslation { +interface ItemTranslation { name?: string; simpleDescription?: string; description?: DescriptionField[]; } -export interface Review { +interface Review { rating?: number; content?: string; userID?: string; @@ -32,10 +32,7 @@ export interface Review { timestamp?: string; } -/** @deprecated Use {@link Review} instead */ -export type Callback = Review; - -export interface Question { +interface Question { question: string; answer: string; upvotes: number; @@ -51,13 +48,13 @@ export interface ItemName { } /** Localized description entry from backend */ -export interface ItemDescription { +interface ItemDescription { language: string; value: string; } /** Key-value attribute pair */ -export interface ItemAttribute { +interface ItemAttribute { key: string; value: string; } @@ -68,7 +65,7 @@ export interface DeliveryOption { deliveryTime: string; } -export type DeliveryMode = 'selectable' | 'digital'; +type DeliveryMode = 'selectable' | 'digital'; /** Item variant detail (price, size, colour per variant) */ export interface ItemDetail { diff --git a/src/app/pages/cart/cart.component.ts b/src/app/pages/cart/cart.component.ts index 45e11d2..2cd1277 100644 --- a/src/app/pages/cart/cart.component.ts +++ b/src/app/pages/cart/cart.component.ts @@ -112,7 +112,6 @@ export class CartComponent implements OnDestroy { } onSwipeStart(itemID: number, event: TouchEvent): void { - const item = event.currentTarget as HTMLElement; const startX = event.touches[0].clientX; const onMove = (e: TouchEvent) => { diff --git a/src/app/pages/category/subcategories.component.ts b/src/app/pages/category/subcategories.component.ts index 1146b10..742483e 100644 --- a/src/app/pages/category/subcategories.component.ts +++ b/src/app/pages/category/subcategories.component.ts @@ -121,11 +121,11 @@ export class SubcategoriesComponent implements OnInit, OnDestroy { } // TrackBy function for performance optimization - trackByCategoryId(index: number, category: Category): number { + trackByCategoryId(_index: number, category: Category): number { return category.categoryID; } - trackBySubId(index: number, sub: Subcategory): string { + trackBySubId(_index: number, sub: Subcategory): string { return sub.id; } diff --git a/src/app/pages/item-detail/item-detail.component.ts b/src/app/pages/item-detail/item-detail.component.ts index 35477da..8501e03 100644 --- a/src/app/pages/item-detail/item-detail.component.ts +++ b/src/app/pages/item-detail/item-detail.component.ts @@ -9,7 +9,7 @@ import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { Subscription } from 'rxjs'; import { environment } from '../../../environments/environment'; import { SecurityContext } from '@angular/core'; -import { getDiscountedPrice, getAllImages, getStockStatus, getBadgeClass, getTranslatedField } from '../../utils/item.utils'; +import { getStockStatus, getBadgeClass, getTranslatedField } from '../../utils/item.utils'; import { LangRoutePipe } from '../../pipes/lang-route.pipe'; import { TranslatePipe } from '../../i18n/translate.pipe'; import { TranslateService } from '../../i18n/translate.service'; @@ -297,7 +297,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy { }; this.apiService.submitReview(reviewData).subscribe({ - next: (response) => { + next: () => { this.reviewSubmitStatus.set('success'); this.newReview = { rating: 0, comment: '', anonymous: false }; diff --git a/src/app/services/api.service.ts b/src/app/services/api.service.ts index c5eec8e..d852ca2 100644 --- a/src/app/services/api.service.ts +++ b/src/app/services/api.service.ts @@ -2,7 +2,8 @@ import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { Observable, timer } from 'rxjs'; import { map, retry } from 'rxjs/operators'; -import { Category, DeliveryOption, Item, Subcategory } from '../models'; +import { Category, DeliveryOption, Item } from '../models'; +import { normalizeDeliveryOption, normalizeOptionalNumber } from '../utils/normalization.utils'; import { environment } from '../../environments/environment'; export interface QrCreateRequest { @@ -69,7 +70,7 @@ export class ApiService { private readonly retryConfig = { count: 2, - delay: (error: unknown, retryCount: number) => timer(Math.pow(2, retryCount) * 500) + delay: (_error: unknown, retryCount: number) => timer(Math.pow(2, retryCount) * 500) }; constructor(private http: HttpClient) {} @@ -86,63 +87,6 @@ export class ApiService { return c.startsWith('0x') ? '#' + c.slice(2) : c; } - private normalizeOptionalNumber(value: unknown): number | undefined { - if (value === null || value === undefined || value === '') { - return undefined; - } - - const normalized = typeof value === 'number' - ? value - : Number(String(value).replace(',', '.')); - - return Number.isFinite(normalized) ? normalized : undefined; - } - - private normalizeOptionalString(value: unknown): string { - if (typeof value === 'string') { - return value.trim(); - } - - if (typeof value === 'number' || typeof value === 'bigint') { - return String(value); - } - - return ''; - } - - private asRecord(value: unknown): Record | null { - return value !== null && typeof value === 'object' && !Array.isArray(value) - ? value as Record - : null; - } - - private normalizeDeliveryOption(value: unknown): DeliveryOption | null { - const source = this.asRecord(value); - if (!source) { - return null; - } - - const deliveryPlace = this.normalizeOptionalString( - source['deliveryPlace'] ?? source['delivery_place'] ?? source['deliveryplace'] - ); - const deliveryTime = this.normalizeOptionalString( - source['deliveryTime'] ?? source['delivery_time'] ?? source['deliverytime'] - ); - const deliveryPrice = this.normalizeOptionalNumber( - source['deliveryPrice'] ?? source['delivery_price'] ?? source['deliveryprice'] - ); - - if (deliveryPrice === undefined && !deliveryPlace && !deliveryTime) { - return null; - } - - return { - deliveryPrice: deliveryPrice ?? 0, - deliveryPlace, - deliveryTime, - }; - } - private normalizeDeliveryData( raw: any, legacyDeliveryPrice?: number @@ -159,7 +103,7 @@ export class ApiService { ? [rawDelivery] : []; const options = deliveryCandidates - .map(candidate => this.normalizeDeliveryOption(candidate)) + .map(candidate => normalizeDeliveryOption(candidate)) .filter((option): option is DeliveryOption => option !== null); if (options.length > 0) { @@ -197,7 +141,7 @@ export class ApiService { private normalizeItem(raw: any): Item { const { partnerID, ...rest } = raw; const item: Item = { ...rest }; - let legacyDeliveryPrice = this.normalizeOptionalNumber( + let legacyDeliveryPrice = normalizeOptionalNumber( raw.deliveryPrice ?? raw.delivery_price ?? raw.deliveryprice ); @@ -210,7 +154,7 @@ export class ApiService { ...d, colour: this.normalizeColor(d.colour || d.color || ''), color: undefined, - deliveryPrice: this.normalizeOptionalNumber( + deliveryPrice: normalizeOptionalNumber( d.deliveryPrice ?? d.delivery_price ?? d.deliveryprice ), })); @@ -219,7 +163,7 @@ export class ApiService { if (!item.colour) item.colour = this.normalizeColor(detail.colour || detail.color || ''); if (!item.size) item.size = detail.size || ''; if (legacyDeliveryPrice === undefined) { - legacyDeliveryPrice = this.normalizeOptionalNumber( + legacyDeliveryPrice = normalizeOptionalNumber( detail.deliveryPrice ?? detail.delivery_price ?? detail.deliveryprice ); } diff --git a/src/app/services/cart.service.ts b/src/app/services/cart.service.ts index 2ace73a..d87c408 100644 --- a/src/app/services/cart.service.ts +++ b/src/app/services/cart.service.ts @@ -1,7 +1,7 @@ -import { Injectable, signal, computed, effect } from '@angular/core'; -import { ApiService } from './api.service'; -import { DeliveryOption, Item, CartItem } from '../models'; +import { Injectable, signal, computed, effect, Injector } from '@angular/core'; +import { DeliveryOption, CartItem } from '../models'; import { getDiscountedPrice } from '../utils/item.utils'; +import { normalizeDeliveryOption, normalizeOptionalNumber } from '../utils/normalization.utils'; import { environment } from '../../environments/environment'; import type { } from '../types/telegram.types'; @@ -48,7 +48,7 @@ export class CartService { && items.some(item => (item.deliveryOptions?.length ?? 0) > 0 || item.selectedDelivery != null); }); - constructor(private apiService: ApiService) { + constructor(private injector: Injector) { this.loadCart(); // Auto-save whenever cart changes (skip the initial empty state) @@ -60,57 +60,6 @@ export class CartService { }); } - private normalizeOptionalNumber(value: unknown): number | undefined { - if (value === null || value === undefined || value === '') { - return undefined; - } - - const normalized = typeof value === 'number' - ? value - : Number(String(value).replace(',', '.')); - - return Number.isFinite(normalized) ? normalized : undefined; - } - - private normalizeOptionalString(value: unknown): string { - if (typeof value === 'string') { - return value.trim(); - } - - if (typeof value === 'number' || typeof value === 'bigint') { - return String(value); - } - - return ''; - } - - private normalizeDeliveryOption(value: unknown): DeliveryOption | null { - if (value === null || value === undefined || typeof value !== 'object' || Array.isArray(value)) { - return null; - } - - const source = value as Record; - const deliveryPlace = this.normalizeOptionalString( - source['deliveryPlace'] ?? source['delivery_place'] ?? source['deliveryplace'] - ); - const deliveryTime = this.normalizeOptionalString( - source['deliveryTime'] ?? source['delivery_time'] ?? source['deliverytime'] - ); - const deliveryPrice = this.normalizeOptionalNumber( - source['deliveryPrice'] ?? source['delivery_price'] ?? source['deliveryprice'] - ); - - if (deliveryPrice === undefined && !deliveryPlace && !deliveryTime) { - return null; - } - - return { - deliveryPrice: deliveryPrice ?? 0, - deliveryPlace, - deliveryTime, - }; - } - private sameDeliveryOption(left: DeliveryOption, right: DeliveryOption): boolean { return left.deliveryPrice === right.deliveryPrice && left.deliveryPlace === right.deliveryPlace @@ -131,10 +80,10 @@ export class CartService { } { const normalizedOptions = Array.isArray(item.deliveryOptions) ? item.deliveryOptions - .map(option => this.normalizeDeliveryOption(option)) + .map(option => normalizeDeliveryOption(option)) .filter((option): option is DeliveryOption => option !== null) : []; - const legacyDeliveryPrice = this.normalizeOptionalNumber(item.deliveryPrice); + const legacyDeliveryPrice = normalizeOptionalNumber(item.deliveryPrice); const deliveryOptions = normalizedOptions.length > 0 ? normalizedOptions : legacyDeliveryPrice !== undefined @@ -148,7 +97,7 @@ export class CartService { const deliverySelectionRequired = deliveryOptions.length > 0 ? item.deliverySelectionRequired !== false && normalizedOptions.length > 0 : false; - const selectedDelivery = this.normalizeDeliveryOption(item.selectedDelivery) + const selectedDelivery = normalizeDeliveryOption(item.selectedDelivery) ?? (deliveryOptions.length === 1 && !deliverySelectionRequired ? deliveryOptions[0] : null); const matchedSelection = selectedDelivery && deliveryOptions.length > 0 ? deliveryOptions.find(option => this.sameDeliveryOption(option, selectedDelivery)) ?? selectedDelivery @@ -251,23 +200,28 @@ export class CartService { } else { // Get item details from API and add to cart this.addingItems.add(itemID); - this.apiService.getItem(itemID).subscribe({ - next: (item) => { - const cartItem = this.normalizeCartItem({ - ...item, - quantity, - ...(variant?.colour != null && { colour: variant.colour }), - ...(variant?.size != null && { size: variant.size }), - ...(variant?.price != null && { price: variant.price }), - ...(variant?.currency != null && { currency: variant.currency }), - }); - this.cartItems.set([...this.cartItems(), cartItem]); - this.addingItems.delete(itemID); - }, - error: (err) => { - console.error('Error adding to cart:', err); - this.addingItems.delete(itemID); - } + import('./api.service').then(({ ApiService }) => { + this.injector.get(ApiService).getItem(itemID).subscribe({ + next: (item) => { + const cartItem = this.normalizeCartItem({ + ...item, + quantity, + ...(variant?.colour != null && { colour: variant.colour }), + ...(variant?.size != null && { size: variant.size }), + ...(variant?.price != null && { price: variant.price }), + ...(variant?.currency != null && { currency: variant.currency }), + }); + this.cartItems.set([...this.cartItems(), cartItem]); + this.addingItems.delete(itemID); + }, + error: (err) => { + console.error('Error adding to cart:', err); + this.addingItems.delete(itemID); + } + }); + }).catch((err) => { + console.error('Error loading API service:', err); + this.addingItems.delete(itemID); }); } } @@ -286,7 +240,7 @@ export class CartService { } setSelectedDelivery(itemID: number, selectedDelivery: DeliveryOption | null): void { - const normalizedSelection = this.normalizeDeliveryOption(selectedDelivery); + const normalizedSelection = normalizeDeliveryOption(selectedDelivery); const updatedItems = this.cartItems().map(item => { if (item.itemID !== itemID) { return item; diff --git a/src/app/types/telegram.types.ts b/src/app/types/telegram.types.ts index ad8c0fb..f54a36a 100644 --- a/src/app/types/telegram.types.ts +++ b/src/app/types/telegram.types.ts @@ -1,4 +1,4 @@ -export interface TelegramUser { +interface TelegramUser { id: number; first_name: string; last_name?: string; @@ -21,3 +21,5 @@ declare global { }; } } + +export {}; diff --git a/src/app/utils/item.utils.ts b/src/app/utils/item.utils.ts index f6115d7..4e9e09b 100644 --- a/src/app/utils/item.utils.ts +++ b/src/app/utils/item.utils.ts @@ -13,25 +13,10 @@ export function getMainImage(item: Item): string { return item.photos?.[0]?.url || '/assets/images/placeholder.svg'; } -export function getAllImages(item: Item): string[] { - if (item.imgs && item.imgs.length > 0) { - return item.imgs; - } - return item.photos?.map(p => p.url) || []; -} - -export function trackByItemId(index: number, item: Item): number | string { +export function trackByItemId(_index: number, item: Item): number | string { return item.id || item.itemID; } -/** - * Get the display description — supports both legacy HTML string - * and structured key-value pairs from backOffice API. - */ -export function hasStructuredDescription(item: Item): boolean { - return Array.isArray(item.descriptionFields) && item.descriptionFields.length > 0; -} - /** * Compute stock status from quantity if the legacy `remainings` field is absent. */ diff --git a/src/app/utils/normalization.utils.ts b/src/app/utils/normalization.utils.ts new file mode 100644 index 0000000..7fe8471 --- /dev/null +++ b/src/app/utils/normalization.utils.ts @@ -0,0 +1,58 @@ +import { DeliveryOption } from '../models'; + +export function normalizeOptionalNumber(value: unknown): number | undefined { + if (value === null || value === undefined || value === '') { + return undefined; + } + + const normalized = typeof value === 'number' + ? value + : Number(String(value).replace(',', '.')); + + return Number.isFinite(normalized) ? normalized : undefined; +} + +function normalizeOptionalString(value: unknown): string { + if (typeof value === 'string') { + return value.trim(); + } + + if (typeof value === 'number' || typeof value === 'bigint') { + return String(value); + } + + return ''; +} + +function asRecord(value: unknown): Record | null { + return value !== null && typeof value === 'object' && !Array.isArray(value) + ? value as Record + : null; +} + +export function normalizeDeliveryOption(value: unknown): DeliveryOption | null { + const source = asRecord(value); + if (!source) { + return null; + } + + const deliveryPlace = normalizeOptionalString( + source['deliveryPlace'] ?? source['delivery_place'] ?? source['deliveryplace'] + ); + const deliveryTime = normalizeOptionalString( + source['deliveryTime'] ?? source['delivery_time'] ?? source['deliverytime'] + ); + const deliveryPrice = normalizeOptionalNumber( + source['deliveryPrice'] ?? source['delivery_price'] ?? source['deliveryprice'] + ); + + if (deliveryPrice === undefined && !deliveryPlace && !deliveryTime) { + return null; + } + + return { + deliveryPrice: deliveryPrice ?? 0, + deliveryPlace, + deliveryTime, + }; +} \ No newline at end of file diff --git a/src/styles.scss b/src/styles.scss index 810948a..8afeb33 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -5,12 +5,6 @@ /* Google Fonts loaded via in index.html for non-blocking rendering */ -/* Font optimization */ -@font-face { - font-family: system-ui; - font-display: swap; -} - /* Default CSS Variables - will be overridden by theme files */ :root { --primary-color: #497671; @@ -191,6 +185,7 @@ a, button, input, textarea, select { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; + line-clamp: 2; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } diff --git a/tsconfig.json b/tsconfig.json index f5f6f32..7ca8d64 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,9 +28,6 @@ "references": [ { "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" } ] } diff --git a/tsconfig.spec.json b/tsconfig.spec.json deleted file mode 100644 index c0fd7bc..0000000 --- a/tsconfig.spec.json +++ /dev/null @@ -1,15 +0,0 @@ -/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ -/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/spec", - "rootDir": "./src", - "types": [ - "jasmine" - ] - }, - "include": [ - "src/**/*.ts" - ] -}