diff --git a/package-lock.json b/package-lock.json index 228777fd..bcc7364b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -274,14 +274,14 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.2003.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2003.14.tgz", - "integrity": "sha512-dVlWqaYu0PIgHTBu16uYUS6lJOIpXCpOYhPWuYwqdo7a4x2HcagPQ+omUZJTA6kukh7ROpKcRoiy/DsO/DgvUA==", + "version": "0.2003.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2003.15.tgz", + "integrity": "sha512-HmGnUTLVwpvOFilc3gTP6CL9o+UbkVyu9S4WENkQbInbW3zp54lkzY71uWJIP7QvuXPa+bS4WHEmoGNQtNvv1A==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@angular-devkit/core": "20.3.14", + "@angular-devkit/core": "20.3.15", "rxjs": "7.8.2" }, "engines": { @@ -290,19 +290,46 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@angular-devkit/architect/node_modules/@angular-devkit/core": { + "version": "20.3.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.3.15.tgz", + "integrity": "sha512-s7sE4S5Hy62dLrtHwizbZaMcupAE8fPhm6rF+jBkhHZ75zXGhGzXP8WKFztYCAuGnis4pPnGSEKP/xVTc2lw6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.3", + "rxjs": "7.8.2", + "source-map": "0.7.6" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, "node_modules/@angular-devkit/build-angular": { - "version": "20.3.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-20.3.14.tgz", - "integrity": "sha512-L3saxbGXUgSSXfCrWHTl9eBAxzcA1oSrb0ojL+NBiJ82Zhx1a3XIGSTNg7YkCrXHaLx+fvuoeyT7xyBH18zYZw==", + "version": "20.3.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-20.3.15.tgz", + "integrity": "sha512-md5ikmdH0rM4jkVFwNQhN++onUUZPUDUfKijnb1XZArQisT9hPiNqTPbO+OZTBK/hQYYV/GfTOhDH30whG32xQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2003.14", - "@angular-devkit/build-webpack": "0.2003.14", - "@angular-devkit/core": "20.3.14", - "@angular/build": "20.3.14", + "@angular-devkit/architect": "0.2003.15", + "@angular-devkit/build-webpack": "0.2003.15", + "@angular-devkit/core": "20.3.15", + "@angular/build": "20.3.15", "@babel/core": "7.28.3", "@babel/generator": "7.28.3", "@babel/helper-annotate-as-pure": "7.27.3", @@ -313,7 +340,7 @@ "@babel/preset-env": "7.28.3", "@babel/runtime": "7.28.3", "@discoveryjs/json-ext": "0.6.3", - "@ngtools/webpack": "20.3.14", + "@ngtools/webpack": "20.3.15", "ansi-colors": "4.1.3", "autoprefixer": "10.4.21", "babel-loader": "10.0.0", @@ -347,7 +374,7 @@ "terser": "5.43.1", "tree-kill": "1.2.2", "tslib": "2.8.1", - "webpack": "5.101.2", + "webpack": "5.104.1", "webpack-dev-middleware": "7.4.2", "webpack-dev-server": "5.2.2", "webpack-merge": "6.0.1", @@ -368,7 +395,7 @@ "@angular/platform-browser": "^20.0.0", "@angular/platform-server": "^20.0.0", "@angular/service-worker": "^20.0.0", - "@angular/ssr": "^20.3.14", + "@angular/ssr": "^20.3.15", "@web/test-runner": "^0.20.0", "browser-sync": "^3.0.2", "jest": "^29.5.0 || ^30.2.0", @@ -424,14 +451,42 @@ } } }, + "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/core": { + "version": "20.3.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.3.15.tgz", + "integrity": "sha512-s7sE4S5Hy62dLrtHwizbZaMcupAE8fPhm6rF+jBkhHZ75zXGhGzXP8WKFztYCAuGnis4pPnGSEKP/xVTc2lw6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.3", + "rxjs": "7.8.2", + "source-map": "0.7.6" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.2003.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.2003.14.tgz", - "integrity": "sha512-kE5bCHnmkWRhCxTlZj1E75UECArc1tq3RC1LMMeJL0Wj6tFO5Y33u16zucXbGqYHZETuz4svR0/u800bjMaQyg==", + "version": "0.2003.15", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.2003.15.tgz", + "integrity": "sha512-u1gjLH0T+s4PiwbSUhzYZUKCsIF9CvTGJoN+Ki+CQqZAlTGLOp2y55VXmdrRX4e3tsKkS+chpQ8sN2b5vbzv9w==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.2003.14", + "@angular-devkit/architect": "0.2003.15", "rxjs": "7.8.2" }, "engines": { @@ -634,14 +689,14 @@ } }, "node_modules/@angular/build": { - "version": "20.3.14", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.3.14.tgz", - "integrity": "sha512-ajFJqTqyI2N9PYcWVxUfb6YEUQsZ13jsBzI/kDpeEZZCGadLJGSMZVNwkX7n9Csw7gzertpenGBXsSTxUjd8TA==", + "version": "20.3.15", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.3.15.tgz", + "integrity": "sha512-DMp/wb3I9/izveXRuOkCTYEQlEzvNlJVnqA215tijOSiJGjYoUsQLazTCxtEx/trftOhVpnMP/2OvvMQVAJJoQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2003.14", + "@angular-devkit/architect": "0.2003.15", "@babel/core": "7.28.3", "@babel/helper-annotate-as-pure": "7.27.3", "@babel/helper-split-export-declaration": "7.24.7", @@ -683,7 +738,7 @@ "@angular/platform-browser": "^20.0.0", "@angular/platform-server": "^20.0.0", "@angular/service-worker": "^20.0.0", - "@angular/ssr": "^20.3.14", + "@angular/ssr": "^20.3.15", "karma": "^6.4.0", "less": "^4.2.0", "ng-packagr": "^20.0.0", @@ -767,22 +822,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { - "version": "0.2003.15", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2003.15.tgz", - "integrity": "sha512-HmGnUTLVwpvOFilc3gTP6CL9o+UbkVyu9S4WENkQbInbW3zp54lkzY71uWJIP7QvuXPa+bS4WHEmoGNQtNvv1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "20.3.15", - "rxjs": "7.8.2" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, "node_modules/@angular/cli/node_modules/@angular-devkit/core": { "version": "20.3.15", "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.3.15.tgz", @@ -1293,6 +1332,8 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, "license": "MIT", "dependencies": { @@ -2689,9 +2730,9 @@ } }, "node_modules/@decaf-ts/cli": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@decaf-ts/cli/-/cli-0.4.4.tgz", - "integrity": "sha512-VxT/aQSZyiZgkMXThmAmbDMrqnSFdvwqYHy8MlTIWttRBGbVuCPE45XbVWZC3Y+qhZNOuBrtI+TBLQfYqgQ8qA==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@decaf-ts/cli/-/cli-0.4.7.tgz", + "integrity": "sha512-BWjEl2kGEKqHxNMrPqo/nkT2wcdjw8zrdfRxwrtHeWoB/vY8LTX2Lx990rPZvYwmV2JHYH/Hvzpxbhm86xdRmg==", "dev": true, "license": "MIT", "dependencies": { @@ -2709,9 +2750,9 @@ } }, "node_modules/@decaf-ts/core": { - "version": "0.8.25", - "resolved": "https://registry.npmjs.org/@decaf-ts/core/-/core-0.8.25.tgz", - "integrity": "sha512-I7XCXdEjeMOl6pK6uzevDJLNGkG5bg9VKkRJOD7AmEj/T3Vr0SVuBkqIFI/OS5S85eCSpmm5A67t/o5jVgIesQ==", + "version": "0.8.41", + "resolved": "https://registry.npmjs.org/@decaf-ts/core/-/core-0.8.41.tgz", + "integrity": "sha512-QiUUeN/ouyl0eM0VF5WwOUVTlQ7HsC7M7lq6x/QmkO5g5G1bGUDKN3si3zfpLSJT5Dp77IjG57pnvxwIZ9Q2EA==", "license": "MPL-2.0", "peer": true, "dependencies": { @@ -2727,9 +2768,9 @@ } }, "node_modules/@decaf-ts/db-decorators": { - "version": "0.8.16", - "resolved": "https://registry.npmjs.org/@decaf-ts/db-decorators/-/db-decorators-0.8.16.tgz", - "integrity": "sha512-fNzPz59KenvMTn6d0+ZDzT+pgKycINdtbUdP4LpcEkEwoGobExw6o0Npc3oLSi1HpQ+VsIGmzeF6XNeklGgI+w==", + "version": "0.8.19", + "resolved": "https://registry.npmjs.org/@decaf-ts/db-decorators/-/db-decorators-0.8.19.tgz", + "integrity": "sha512-j9xPvAvmHsjcVZClB+FV8ndFTOH4dzx9PJ6TMDiIF9IkCRFO+AgllzOS/4I+oQvN1hKFYq1MbHI1/05RgQa5Gw==", "license": "MIT", "peer": true, "dependencies": { @@ -2744,9 +2785,9 @@ } }, "node_modules/@decaf-ts/decoration": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/@decaf-ts/decoration/-/decoration-0.8.6.tgz", - "integrity": "sha512-I977/GHpjg/wOrTH2EKRFvqTVnb2CzJ4Ii90tr4EPCNpJ4CsmnYxTo+EBqh5FPyu9xp6JSpfG8mo08JpInYX6w==", + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/@decaf-ts/decoration/-/decoration-0.8.7.tgz", + "integrity": "sha512-zZ7P2raTx+XYpVMSA9bucQ5rrjP3Pmyfn90M3qZvgdO5iOgvF7M1kwunHulUAxpKPvNHKTD6RghxDB9EwKlSXA==", "license": "MIT", "peer": true, "dependencies": { @@ -2758,9 +2799,9 @@ } }, "node_modules/@decaf-ts/decorator-validation": { - "version": "1.11.16", - "resolved": "https://registry.npmjs.org/@decaf-ts/decorator-validation/-/decorator-validation-1.11.16.tgz", - "integrity": "sha512-nyNsF66JRS91+0RzxiTfs+gdIoHR0qbQatH718uqkQ2+oSF280DI0fm5rg1U81Mmfi0QlpY5Jmn5SnB6I6XvRQ==", + "version": "1.11.18", + "resolved": "https://registry.npmjs.org/@decaf-ts/decorator-validation/-/decorator-validation-1.11.18.tgz", + "integrity": "sha512-9yD52I5uMcY2/P/A6y2NoPh5D7qFhnQKX0X5Dek03qy1J/oy51GIEhYjZ9V8tmkONpUncRmFDiJ7TzFG1O8VmA==", "license": "MIT", "peer": true, "dependencies": { @@ -2772,9 +2813,9 @@ } }, "node_modules/@decaf-ts/for-http": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@decaf-ts/for-http/-/for-http-0.3.36.tgz", - "integrity": "sha512-joBfdfIX4Hzx7EXN7E/R46DobUi0XLnmDPaLAZ64HE/+hONGUh4SrtllJ/zsczaPdnJVye9Apthym53cYULP7w==", + "version": "0.3.41", + "resolved": "https://registry.npmjs.org/@decaf-ts/for-http/-/for-http-0.3.41.tgz", + "integrity": "sha512-CzR121zvb34MEOWrl2wyGA1vGiGhfv2HJjklmcdFeXRQp9giKPrcJfLh8g6vgNLLyP1erqLzkBAXynYsD4VtDg==", "license": "MIT", "peer": true, "dependencies": { @@ -2785,7 +2826,8 @@ "@decaf-ts/injectable-decorators": "latest", "@decaf-ts/logging": "latest", "@decaf-ts/transactional-decorators": "latest", - "axios": "^1.13.2" + "axios": "^1.13.2", + "event-source-plus": "^0.1.15" }, "engines": { "node": ">=20.0.0", @@ -2793,9 +2835,9 @@ } }, "node_modules/@decaf-ts/injectable-decorators": { - "version": "1.9.10", - "resolved": "https://registry.npmjs.org/@decaf-ts/injectable-decorators/-/injectable-decorators-1.9.10.tgz", - "integrity": "sha512-qEARNcVYDAl3PKD89f4rChNJEBBH6+ru26oVvhi6OUxg2oHyCNpLv7CppL9aTdvpvFH6iiGEwtlmwiQrAgOE7Q==", + "version": "1.9.11", + "resolved": "https://registry.npmjs.org/@decaf-ts/injectable-decorators/-/injectable-decorators-1.9.11.tgz", + "integrity": "sha512-tHYJprPSL7to7hA4GOu6EptVw7qtm10ikDbxfGwt06NM7a020e74X7CELxdnwOJdt0JOij4Ka+YTvbxuXFzznw==", "license": "MIT", "peer": true, "dependencies": { @@ -2807,9 +2849,9 @@ } }, "node_modules/@decaf-ts/logging": { - "version": "0.10.8", - "resolved": "https://registry.npmjs.org/@decaf-ts/logging/-/logging-0.10.8.tgz", - "integrity": "sha512-VqyfFdFjB8Fs9+GJcUIQmZlak2SU0Qacuk6nRgZIFUTWLGd1lthAuwBnemrwItR++ctMWI4EWLx2UZQCpLXNnQ==", + "version": "0.10.13", + "resolved": "https://registry.npmjs.org/@decaf-ts/logging/-/logging-0.10.13.tgz", + "integrity": "sha512-293m9wuDtUts326iSoFyA849ofbAJdco5P5aAQPXz83122G17488Z+e39PMI+54YJg0y2c6rFAGUkWqJrLLTYA==", "license": "MIT", "peer": true, "dependencies": { @@ -2837,9 +2879,9 @@ } }, "node_modules/@decaf-ts/transactional-decorators": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@decaf-ts/transactional-decorators/-/transactional-decorators-0.3.5.tgz", - "integrity": "sha512-ChDeLklsAvVba8pfSwbsWMuzA0iOAqMhoYA4pM8zAnqNQvIacxgM0hGymq+b2lZqeFPCzb9ZsrsLCXuX+xSbLQ==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@decaf-ts/transactional-decorators/-/transactional-decorators-0.3.6.tgz", + "integrity": "sha512-J5c4wtmHO1GNHD/GfjeBPwmhBjTv47PI+TFuYoKD6PNNQ7qaCiq5f4eCU/5u5ak2iRUp8EOhfggedBVe8LVrsg==", "license": "MIT", "peer": true, "dependencies": { @@ -2854,9 +2896,9 @@ } }, "node_modules/@decaf-ts/ui-decorators": { - "version": "0.6.13", - "resolved": "https://registry.npmjs.org/@decaf-ts/ui-decorators/-/ui-decorators-0.6.13.tgz", - "integrity": "sha512-yzWO/kagMj21nxaJ6PMfJxvZJ7WItHmx+x69EgNzWLK6ij6V3oomCaevldnqHadgK+XixyEaIPoPdv/ed6H0IA==", + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/@decaf-ts/ui-decorators/-/ui-decorators-0.6.15.tgz", + "integrity": "sha512-Asy4lFO0hjoE5l9LIOq5Xmd1mvo0zFomGPlfMqftgxqBC7BK6hpot0LzRgvUF2ODOZFDux5CNaG6BmusS6jL5w==", "license": "MPL-2.0 OR AGPL-3.0", "peer": true, "dependencies": { @@ -2870,9 +2912,9 @@ } }, "node_modules/@decaf-ts/utils": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@decaf-ts/utils/-/utils-0.11.8.tgz", - "integrity": "sha512-xHOt0joNDoduESrkam8h36AFSnAnpt5RXDuX7DKbs+WpoL2W7aUk+2bYsIqRImxfX2k0BlkPhtOGWUQoeTmkBA==", + "version": "0.11.9", + "resolved": "https://registry.npmjs.org/@decaf-ts/utils/-/utils-0.11.9.tgz", + "integrity": "sha512-teIw6DzaBmR0CMRECtIyMw6V8Ftwh7/a2Nq4Ql+gQ/TDoO0sknJ0lkM49aN+KeR8Ycfy+FJKK5dT++Z+bu51qg==", "dev": true, "license": "MIT", "dependencies": { @@ -4178,7 +4220,9 @@ } }, "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz", + "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5302,6 +5346,8 @@ }, "node_modules/@jsonjoy.com/base64": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5316,7 +5362,9 @@ } }, "node_modules/@jsonjoy.com/buffers": { - "version": "1.2.1", + "version": "17.65.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.65.0.tgz", + "integrity": "sha512-eBrIXd0/Ld3p9lpDDlMaMn6IEfWqtHMD+z61u0JrIiPzsV1r7m6xDZFRxJyvIFTEO+SWdYF9EiQbXZGd8BzPfA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5332,8 +5380,286 @@ }, "node_modules/@jsonjoy.com/codegen": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz", + "integrity": "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-core": { + "version": "4.56.10", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.56.10.tgz", + "integrity": "sha512-PyAEA/3cnHhsGcdY+AmIU+ZPqTuZkDhCXQ2wkXypdLitSpd6d5Ivxhnq4wa2ETRWFVJGabYynBWxIijOswSmOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.56.10", + "@jsonjoy.com/fs-node-utils": "4.56.10", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-fsa": { + "version": "4.56.10", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.56.10.tgz", + "integrity": "sha512-/FVK63ysNzTPOnCCcPoPHt77TOmachdMS422txM4KhxddLdbW1fIbFMYH0AM0ow/YchCyS5gqEjKLNyv71j/5Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.56.10", + "@jsonjoy.com/fs-node-builtins": "4.56.10", + "@jsonjoy.com/fs-node-utils": "4.56.10", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node": { + "version": "4.56.10", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.56.10.tgz", + "integrity": "sha512-7R4Gv3tkUdW3dXfXiOkqxkElxKNVdd8BDOWC0/dbERd0pXpPY+s2s1Mino+aTvkGrFPiY+mmVxA7zhskm4Ue4Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.56.10", + "@jsonjoy.com/fs-node-builtins": "4.56.10", + "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/fs-print": "4.56.10", + "@jsonjoy.com/fs-snapshot": "4.56.10", + "glob-to-regex.js": "^1.0.0", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-builtins": { + "version": "4.56.10", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.56.10.tgz", + "integrity": "sha512-uUnKz8R0YJyKq5jXpZtkGV9U0pJDt8hmYcLRrPjROheIfjMXsz82kXMgAA/qNg0wrZ1Kv+hrg7azqEZx6XZCVw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-to-fsa": { + "version": "4.56.10", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.56.10.tgz", + "integrity": "sha512-oH+O6Y4lhn9NyG6aEoFwIBNKZeYy66toP5LJcDOMBgL99BKQMUf/zWJspdRhMdn/3hbzQsZ8EHHsuekbFLGUWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-fsa": "4.56.10", + "@jsonjoy.com/fs-node-builtins": "4.56.10", + "@jsonjoy.com/fs-node-utils": "4.56.10" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-utils": { + "version": "4.56.10", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.56.10.tgz", + "integrity": "sha512-8EuPBgVI2aDPwFdaNQeNpHsyqPi3rr+85tMNG/lHvQLiVjzoZsvxA//Xd8aB567LUhy4QS03ptT+unkD/DIsNg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.56.10" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-print": { + "version": "4.56.10", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.56.10.tgz", + "integrity": "sha512-JW4fp5mAYepzFsSGrQ48ep8FXxpg4niFWHdF78wDrFGof7F3tKDJln72QFDEn/27M1yHd4v7sKHHVPh78aWcEw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-utils": "4.56.10", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot": { + "version": "4.56.10", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.56.10.tgz", + "integrity": "sha512-DkR6l5fj7+qj0+fVKm/OOXMGfDFCGXLfyHkORH3DF8hxkpDgIHbhf/DwncBMs2igu/ST7OEkexn1gIqoU6Y+9g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^17.65.0", + "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/json-pack": "^17.65.0", + "@jsonjoy.com/util": "^17.65.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { + "version": "17.65.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.65.0.tgz", + "integrity": "sha512-Xrh7Fm/M0QAYpekSgmskdZYnFdSGnsxJ/tHaolA4bNwWdG9i65S8m83Meh7FOxyJyQAdo4d4J97NOomBLEfkDQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { + "version": "17.65.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.65.0.tgz", + "integrity": "sha512-7MXcRYe7n3BG+fo3jicvjB0+6ypl2Y/bQp79Sp7KeSiiCgLqw4Oled6chVv07/xLVTdo3qa1CD0VCCnPaw+RGA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { + "version": "17.65.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.65.0.tgz", + "integrity": "sha512-e0SG/6qUCnVhHa0rjDJHgnXnbsacooHVqQHxspjvlYQSkHm+66wkHw6Gql+3u/WxI/b1VsOdUi0M+fOtkgKGdQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "17.65.0", + "@jsonjoy.com/buffers": "17.65.0", + "@jsonjoy.com/codegen": "17.65.0", + "@jsonjoy.com/json-pointer": "17.65.0", + "@jsonjoy.com/util": "17.65.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { + "version": "17.65.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.65.0.tgz", + "integrity": "sha512-uhTe+XhlIZpWOxgPcnO+iSCDgKKBpwkDVTyYiXX9VayGV8HSFVJM67M6pUE71zdnXF1W0Da21AvnhlmdwYPpow==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/util": "17.65.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { + "version": "17.65.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.65.0.tgz", + "integrity": "sha512-cWiEHZccQORf96q2y6zU3wDeIVPeidmGqd9cNKJRYoVHTV0S1eHPy5JTbHpMnGfDvtvujQwQozOqgO9ABu6h0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "17.65.0", + "@jsonjoy.com/codegen": "17.65.0" + }, "engines": { "node": ">=10.0" }, @@ -5347,6 +5673,8 @@ }, "node_modules/@jsonjoy.com/json-pack": { "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz", + "integrity": "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5370,8 +5698,27 @@ "tslib": "2" } }, + "node_modules/@jsonjoy.com/json-pack/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/@jsonjoy.com/json-pointer": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", + "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5391,6 +5738,8 @@ }, "node_modules/@jsonjoy.com/util": { "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz", + "integrity": "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5408,8 +5757,27 @@ "tslib": "2" } }, + "node_modules/@jsonjoy.com/util/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "dev": true, "license": "MIT" }, @@ -5486,6 +5854,8 @@ }, "node_modules/@lmdb/lmdb-linux-x64": { "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.4.2.tgz", + "integrity": "sha512-vL9nM17C77lohPYE4YaAQvfZCSVJSryE4fXdi8M7uWPBnU+9DJabgKVAeyDb84ZM2vcFseoBE4/AagVtJeRE7g==", "cpu": [ "x64" ], @@ -5636,6 +6006,8 @@ }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", "cpu": [ "x64" ], @@ -5978,9 +6350,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "20.3.14", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-20.3.14.tgz", - "integrity": "sha512-2rI9naKQBtoyQmddCnPp94o0lQVl5VPsCefntMg2T0XCCdyNj2OK4X4QCVRrtAcTwlYMysDSTpPKE/VkPcjIQA==", + "version": "20.3.15", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-20.3.15.tgz", + "integrity": "sha512-7bH91SdVN9xawMg4G+OoQG+nFz9/huUXx/MptR5iOsuRUpNo3PQwMNr07VTRV8o4YAtTTRIf2Yam4fNkb3rRAg==", "dev": true, "license": "MIT", "engines": { @@ -7922,6 +8294,8 @@ }, "node_modules/@types/body-parser": { "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "dev": true, "license": "MIT", "dependencies": { @@ -7931,6 +8305,8 @@ }, "node_modules/@types/bonjour": { "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7958,6 +8334,8 @@ }, "node_modules/@types/connect": { "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, "license": "MIT", "dependencies": { @@ -7966,6 +8344,8 @@ }, "node_modules/@types/connect-history-api-fallback": { "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", "dev": true, "license": "MIT", "dependencies": { @@ -8004,6 +8384,8 @@ }, "node_modules/@types/express": { "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", "dev": true, "license": "MIT", "dependencies": { @@ -8014,7 +8396,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.7", + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", "dev": true, "license": "MIT", "dependencies": { @@ -8039,6 +8423,8 @@ }, "node_modules/@types/http-errors": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", "dev": true, "license": "MIT" }, @@ -8122,6 +8508,8 @@ }, "node_modules/@types/mime": { "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true, "license": "MIT" }, @@ -8135,6 +8523,8 @@ }, "node_modules/@types/node-forge": { "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", "dev": true, "license": "MIT", "dependencies": { @@ -8157,11 +8547,15 @@ }, "node_modules/@types/qs": { "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", "dev": true, "license": "MIT" }, "node_modules/@types/range-parser": { "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true, "license": "MIT" }, @@ -8181,11 +8575,15 @@ }, "node_modules/@types/retry": { "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "dev": true, "license": "MIT" }, "node_modules/@types/send": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8194,6 +8592,8 @@ }, "node_modules/@types/serve-index": { "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", "dev": true, "license": "MIT", "dependencies": { @@ -8202,6 +8602,8 @@ }, "node_modules/@types/serve-static": { "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", "dev": true, "license": "MIT", "dependencies": { @@ -8212,6 +8614,8 @@ }, "node_modules/@types/serve-static/node_modules/@types/send": { "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", "dev": true, "license": "MIT", "dependencies": { @@ -8228,6 +8632,8 @@ }, "node_modules/@types/sockjs": { "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", "dev": true, "license": "MIT", "dependencies": { @@ -8253,6 +8659,8 @@ }, "node_modules/@types/ws": { "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "dev": true, "license": "MIT", "dependencies": { @@ -8854,6 +9262,8 @@ }, "node_modules/@vitejs/plugin-basic-ssl": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.0.tgz", + "integrity": "sha512-dOxxrhgyDIEUADhb/8OlV9JIqYLgos03YorAueTIeOUskLJSEsfwCByjbu98ctXitUN3znXKp0bYD/WHSudCeA==", "dev": true, "license": "MIT", "engines": { @@ -9392,6 +9802,8 @@ }, "node_modules/array-flatten": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true, "license": "MIT" }, @@ -9693,11 +10105,15 @@ }, "node_modules/batch": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true, "license": "MIT" }, "node_modules/beasties": { "version": "0.3.5", + "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.3.5.tgz", + "integrity": "sha512-NaWu+f4YrJxEttJSm16AzMIFtVldCvaJ68b1L098KpqXmxt9xOLtKoLkKxb8ekhOrLqEJAbvT6n6SEvB/sac7A==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -9833,6 +10249,8 @@ }, "node_modules/bonjour-service": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", "dev": true, "license": "MIT", "dependencies": { @@ -9946,6 +10364,8 @@ }, "node_modules/bundle-name": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, "license": "MIT", "dependencies": { @@ -10571,6 +10991,8 @@ }, "node_modules/compressible": { "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, "license": "MIT", "dependencies": { @@ -10582,6 +11004,8 @@ }, "node_modules/compression": { "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "dev": true, "license": "MIT", "dependencies": { @@ -10599,6 +11023,8 @@ }, "node_modules/compression/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { @@ -10607,11 +11033,15 @@ }, "node_modules/compression/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, "node_modules/compression/node_modules/negotiator": { "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "dev": true, "license": "MIT", "engines": { @@ -10639,6 +11069,8 @@ }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", "dev": true, "license": "MIT", "engines": { @@ -10733,6 +11165,8 @@ }, "node_modules/core-util-is": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true, "license": "MIT" }, @@ -10872,6 +11306,8 @@ }, "node_modules/css-select": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-6.0.0.tgz", + "integrity": "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10887,6 +11323,8 @@ }, "node_modules/css-what": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-7.0.0.tgz", + "integrity": "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -11007,7 +11445,9 @@ } }, "node_modules/default-browser": { - "version": "5.4.0", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", "dev": true, "license": "MIT", "dependencies": { @@ -11023,6 +11463,8 @@ }, "node_modules/default-browser-id": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", "dev": true, "license": "MIT", "engines": { @@ -11045,6 +11487,8 @@ }, "node_modules/define-lazy-prop": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "license": "MIT", "engines": { @@ -11085,8 +11529,16 @@ "node": ">=6" } }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, "node_modules/destroy": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "license": "MIT", "engines": { @@ -11096,6 +11548,8 @@ }, "node_modules/detect-libc": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", "optional": true, @@ -11113,6 +11567,8 @@ }, "node_modules/detect-node": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true, "license": "MIT" }, @@ -11136,6 +11592,8 @@ }, "node_modules/dns-packet": { "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", "dev": true, "license": "MIT", "dependencies": { @@ -11171,6 +11629,8 @@ }, "node_modules/dom-serializer": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "license": "MIT", "dependencies": { @@ -11206,6 +11666,8 @@ }, "node_modules/domhandler": { "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -11220,6 +11682,8 @@ }, "node_modules/domutils": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -12044,6 +12508,15 @@ "node": ">= 0.6" } }, + "node_modules/event-source-plus": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/event-source-plus/-/event-source-plus-0.1.15.tgz", + "integrity": "sha512-kt3z/UwDbZxHttynwmXlqTf1qknWqPgswsbvSok1ob6SveMts4BqRXow6aiwB55xTY1XvSXuhn+IvYQErWLyKA==", + "license": "MIT", + "dependencies": { + "ofetch": "^1.5.1" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "dev": true, @@ -12261,6 +12734,8 @@ }, "node_modules/faye-websocket": { "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -12902,6 +13377,8 @@ }, "node_modules/glob-to-regex.js": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -12953,6 +13430,8 @@ }, "node_modules/handle-thing": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true, "license": "MIT" }, @@ -13034,9 +13513,9 @@ } }, "node_modules/hono": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.4.tgz", - "integrity": "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==", + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.8.tgz", + "integrity": "sha512-eVkB/CYCCei7K2WElZW9yYQFWssG0DhaDhVvr7wy5jJ22K+ck8fWW0EsLpB0sITUTvPnc97+rrbQqIr5iqiy9Q==", "dev": true, "license": "MIT", "peer": true, @@ -13065,6 +13544,8 @@ }, "node_modules/hpack.js": { "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13076,6 +13557,8 @@ }, "node_modules/hpack.js/node_modules/readable-stream": { "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", "dependencies": { @@ -13090,11 +13573,15 @@ }, "node_modules/hpack.js/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "license": "MIT" }, "node_modules/hpack.js/node_modules/string_decoder": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", "dependencies": { @@ -13193,7 +13680,9 @@ } }, "node_modules/htmlparser2": { - "version": "10.0.0", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", "dev": true, "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", @@ -13206,12 +13695,14 @@ "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", - "domutils": "^3.2.1", - "entities": "^6.0.0" + "domutils": "^3.2.2", + "entities": "^7.0.1" } }, "node_modules/htmlparser2/node_modules/entities": { - "version": "6.0.1", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -13230,6 +13721,8 @@ }, "node_modules/http-deceiver": { "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", "dev": true, "license": "MIT" }, @@ -13254,6 +13747,8 @@ }, "node_modules/http-parser-js": { "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", "dev": true, "license": "MIT" }, @@ -13345,6 +13840,8 @@ }, "node_modules/hyperdyperid": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", "dev": true, "license": "MIT", "engines": { @@ -13594,6 +14091,8 @@ }, "node_modules/is-docker": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, "license": "MIT", "bin": { @@ -13646,6 +14145,8 @@ }, "node_modules/is-inside-container": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, "license": "MIT", "dependencies": { @@ -13679,6 +14180,8 @@ }, "node_modules/is-network-error": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", + "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", "dev": true, "license": "MIT", "engines": { @@ -13698,6 +14201,8 @@ }, "node_modules/is-plain-obj": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, "license": "MIT", "engines": { @@ -13762,6 +14267,8 @@ }, "node_modules/is-wsl": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "license": "MIT", "dependencies": { @@ -13776,6 +14283,8 @@ }, "node_modules/isarray": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, "license": "MIT" }, @@ -15968,6 +16477,8 @@ }, "node_modules/launch-editor": { "version": "2.12.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.12.0.tgz", + "integrity": "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==", "dev": true, "license": "MIT", "dependencies": { @@ -16189,6 +16700,8 @@ }, "node_modules/lmdb": { "version": "3.4.2", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.4.2.tgz", + "integrity": "sha512-nwVGUfTBUwJKXd6lRV8pFNfnrCC1+l49ESJRM19t/tFb/97QfJEixe5DYRvug5JO7DSFKoKaVy7oGMt5rVqZvg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -16646,6 +17159,8 @@ }, "node_modules/methods": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true, "license": "MIT", "engines": { @@ -16757,6 +17272,8 @@ }, "node_modules/minimalistic-assert": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true, "license": "ISC" }, @@ -16946,6 +17463,8 @@ }, "node_modules/mrmime": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "dev": true, "license": "MIT", "engines": { @@ -16959,6 +17478,8 @@ }, "node_modules/msgpackr": { "version": "1.11.8", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.8.tgz", + "integrity": "sha512-bC4UGzHhVvgDNS7kn9tV8fAucIYUBuGojcaLiz7v+P63Lmtm0Xeji8B/8tYKddALXxJLpwIeBmUN3u64C4YkRA==", "dev": true, "license": "MIT", "optional": true, @@ -16968,6 +17489,8 @@ }, "node_modules/msgpackr-extract": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -16989,6 +17512,8 @@ }, "node_modules/multicast-dns": { "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dev": true, "license": "MIT", "dependencies": { @@ -17143,12 +17668,22 @@ }, "node_modules/node-addon-api": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", "dev": true, "license": "MIT", "optional": true }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" + }, "node_modules/node-forge": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", + "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", "dev": true, "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { @@ -17182,6 +17717,8 @@ }, "node_modules/node-gyp-build-optional-packages": { "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", "dev": true, "license": "MIT", "optional": true, @@ -17575,9 +18112,22 @@ }, "node_modules/obuf": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true, "license": "MIT" }, + "node_modules/ofetch": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" + } + }, "node_modules/on-exit-leak-free": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", @@ -17601,6 +18151,8 @@ }, "node_modules/on-headers": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true, "license": "MIT", "engines": { @@ -17641,6 +18193,8 @@ }, "node_modules/open": { "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", "dev": true, "license": "MIT", "dependencies": { @@ -17727,7 +18281,9 @@ } }, "node_modules/ordered-binary": { - "version": "1.6.0", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.1.tgz", + "integrity": "sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==", "dev": true, "license": "MIT", "optional": true @@ -17775,6 +18331,8 @@ }, "node_modules/p-retry": { "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", "dev": true, "license": "MIT", "dependencies": { @@ -17791,6 +18349,8 @@ }, "node_modules/p-retry/node_modules/retry": { "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, "license": "MIT", "engines": { @@ -17919,6 +18479,8 @@ }, "node_modules/parse5-html-rewriting-stream": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-8.0.0.tgz", + "integrity": "sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==", "dev": true, "license": "MIT", "dependencies": { @@ -17932,6 +18494,8 @@ }, "node_modules/parse5-html-rewriting-stream/node_modules/entities": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -17943,6 +18507,8 @@ }, "node_modules/parse5-html-rewriting-stream/node_modules/parse5": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "dev": true, "license": "MIT", "dependencies": { @@ -17954,6 +18520,8 @@ }, "node_modules/parse5-sax-parser": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-8.0.0.tgz", + "integrity": "sha512-/dQ8UzHZwnrzs3EvDj6IkKrD/jIZyTlB+8XrHJvcjNgRdmWruNdN9i9RK/JtxakmlUdPwKubKPTCqvbTgzGhrw==", "dev": true, "license": "MIT", "dependencies": { @@ -17965,6 +18533,8 @@ }, "node_modules/parse5-sax-parser/node_modules/entities": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -17976,6 +18546,8 @@ }, "node_modules/parse5-sax-parser/node_modules/parse5": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "dev": true, "license": "MIT", "dependencies": { @@ -18366,6 +18938,8 @@ }, "node_modules/postcss-media-query-parser": { "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", "dev": true, "license": "MIT" }, @@ -18534,6 +19108,8 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, "license": "MIT" }, @@ -19478,6 +20054,8 @@ }, "node_modules/run-applescript": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", "dev": true, "license": "MIT", "engines": { @@ -19555,6 +20133,7 @@ "version": "1.90.0", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -19671,11 +20250,15 @@ }, "node_modules/select-hose": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", "dev": true, "license": "MIT" }, "node_modules/selfsigned": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -19731,24 +20314,32 @@ } }, "node_modules/serve-index": { - "version": "1.9.1", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz", + "integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==", "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.4", + "accepts": "~1.3.8", "batch": "0.6.1", "debug": "2.6.9", "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "http-errors": "~1.8.0", + "mime-types": "~2.1.35", + "parseurl": "~1.3.3" }, "engines": { "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/serve-index/node_modules/accepts": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", "dependencies": { @@ -19761,6 +20352,8 @@ }, "node_modules/serve-index/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { @@ -19769,6 +20362,8 @@ }, "node_modules/serve-index/node_modules/depd": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, "license": "MIT", "engines": { @@ -19776,26 +20371,26 @@ } }, "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dev": true, "license": "MIT", "dependencies": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" }, "engines": { "node": ">= 0.6" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "dev": true, - "license": "ISC" - }, "node_modules/serve-index/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==", "dev": true, "license": "MIT", "engines": { @@ -19804,6 +20399,8 @@ }, "node_modules/serve-index/node_modules/mime-types": { "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", "dependencies": { @@ -19815,24 +20412,25 @@ }, "node_modules/serve-index/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, "node_modules/serve-index/node_modules/negotiator": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "dev": true, - "license": "ISC" - }, "node_modules/serve-index/node_modules/statuses": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, "license": "MIT", "engines": { @@ -20068,6 +20666,8 @@ }, "node_modules/sockjs": { "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -20217,6 +20817,8 @@ }, "node_modules/spdy": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, "license": "MIT", "dependencies": { @@ -20232,6 +20834,8 @@ }, "node_modules/spdy-transport": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, "license": "MIT", "dependencies": { @@ -20606,9 +21210,9 @@ } }, "node_modules/tar": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.6.tgz", - "integrity": "sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", + "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -20780,6 +21384,8 @@ }, "node_modules/thingies": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", + "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", "dev": true, "license": "MIT", "engines": { @@ -20808,6 +21414,8 @@ }, "node_modules/thunky": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true, "license": "MIT" }, @@ -20914,6 +21522,8 @@ }, "node_modules/tree-dump": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -21890,6 +22500,12 @@ "dev": true, "license": "MIT" }, + "node_modules/ufo": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "license": "MIT" + }, "node_modules/uglify-js": { "version": "3.19.3", "dev": true, @@ -22065,6 +22681,8 @@ }, "node_modules/utils-merge": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, "license": "MIT", "engines": { @@ -22251,6 +22869,8 @@ }, "node_modules/wbuf": { "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, "license": "MIT", "dependencies": { @@ -22267,6 +22887,8 @@ }, "node_modules/weak-lru-cache": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", + "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", "dev": true, "license": "MIT", "optional": true @@ -22280,7 +22902,9 @@ } }, "node_modules/webpack": { - "version": "5.101.2", + "version": "5.104.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", + "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", "dev": true, "license": "MIT", "peer": true, @@ -22293,22 +22917,22 @@ "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", - "browserslist": "^4.24.0", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.3", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.17.4", + "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", + "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^4.3.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.1", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.16", + "watchpack": "^2.4.4", "webpack-sources": "^3.3.3" }, "bin": { @@ -22329,6 +22953,8 @@ }, "node_modules/webpack-dev-middleware": { "version": "7.4.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", + "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", "dev": true, "license": "MIT", "dependencies": { @@ -22356,10 +22982,20 @@ } }, "node_modules/webpack-dev-middleware/node_modules/memfs": { - "version": "4.51.1", + "version": "4.56.10", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.56.10.tgz", + "integrity": "sha512-eLvzyrwqLHnLYalJP7YZ3wBe79MXktMdfQbvMrVD80K+NhrIukCVBvgP30zTJYEEDh9hZ/ep9z0KOdD7FSHo7w==", "dev": true, "license": "Apache-2.0", "dependencies": { + "@jsonjoy.com/fs-core": "4.56.10", + "@jsonjoy.com/fs-fsa": "4.56.10", + "@jsonjoy.com/fs-node": "4.56.10", + "@jsonjoy.com/fs-node-builtins": "4.56.10", + "@jsonjoy.com/fs-node-to-fsa": "4.56.10", + "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/fs-print": "4.56.10", + "@jsonjoy.com/fs-snapshot": "4.56.10", "@jsonjoy.com/json-pack": "^1.11.0", "@jsonjoy.com/util": "^1.9.0", "glob-to-regex.js": "^1.0.1", @@ -22370,10 +23006,15 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, "node_modules/webpack-dev-middleware/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==", "dev": true, "license": "MIT", "engines": { @@ -22382,6 +23023,8 @@ }, "node_modules/webpack-dev-middleware/node_modules/mime-types": { "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", "dependencies": { @@ -22393,9 +23036,10 @@ }, "node_modules/webpack-dev-server": { "version": "5.2.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", + "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", @@ -22450,6 +23094,8 @@ }, "node_modules/webpack-dev-server/node_modules/accepts": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", "dependencies": { @@ -22462,6 +23108,8 @@ }, "node_modules/webpack-dev-server/node_modules/body-parser": { "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "dev": true, "license": "MIT", "dependencies": { @@ -22485,6 +23133,8 @@ }, "node_modules/webpack-dev-server/node_modules/chokidar": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", "dependencies": { @@ -22508,6 +23158,8 @@ }, "node_modules/webpack-dev-server/node_modules/content-disposition": { "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -22519,11 +23171,15 @@ }, "node_modules/webpack-dev-server/node_modules/cookie-signature": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "dev": true, "license": "MIT" }, "node_modules/webpack-dev-server/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { @@ -22532,11 +23188,15 @@ }, "node_modules/webpack-dev-server/node_modules/debug/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, "node_modules/webpack-dev-server/node_modules/express": { "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "dev": true, "license": "MIT", "dependencies": { @@ -22582,6 +23242,8 @@ }, "node_modules/webpack-dev-server/node_modules/finalhandler": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", "dev": true, "license": "MIT", "dependencies": { @@ -22599,6 +23261,8 @@ }, "node_modules/webpack-dev-server/node_modules/fresh": { "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, "license": "MIT", "engines": { @@ -22607,6 +23271,8 @@ }, "node_modules/webpack-dev-server/node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { @@ -22618,6 +23284,8 @@ }, "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", "dev": true, "license": "MIT", "dependencies": { @@ -22641,6 +23309,8 @@ }, "node_modules/webpack-dev-server/node_modules/iconv-lite": { "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "license": "MIT", "dependencies": { @@ -22652,6 +23322,8 @@ }, "node_modules/webpack-dev-server/node_modules/ipaddr.js": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", + "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", "dev": true, "license": "MIT", "engines": { @@ -22660,6 +23332,8 @@ }, "node_modules/webpack-dev-server/node_modules/media-typer": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, "license": "MIT", "engines": { @@ -22668,6 +23342,8 @@ }, "node_modules/webpack-dev-server/node_modules/merge-descriptors": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true, "license": "MIT", "funding": { @@ -22676,6 +23352,8 @@ }, "node_modules/webpack-dev-server/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==", "dev": true, "license": "MIT", "engines": { @@ -22684,6 +23362,8 @@ }, "node_modules/webpack-dev-server/node_modules/mime-types": { "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", "dependencies": { @@ -22695,6 +23375,8 @@ }, "node_modules/webpack-dev-server/node_modules/negotiator": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", "engines": { @@ -22703,11 +23385,15 @@ }, "node_modules/webpack-dev-server/node_modules/path-to-regexp": { "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true, "license": "MIT" }, "node_modules/webpack-dev-server/node_modules/picomatch": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { @@ -22719,6 +23405,8 @@ }, "node_modules/webpack-dev-server/node_modules/raw-body": { "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "license": "MIT", "dependencies": { @@ -22733,6 +23421,8 @@ }, "node_modules/webpack-dev-server/node_modules/readdirp": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", "dependencies": { @@ -22744,6 +23434,8 @@ }, "node_modules/webpack-dev-server/node_modules/send": { "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", "dev": true, "license": "MIT", "dependencies": { @@ -22767,6 +23459,8 @@ }, "node_modules/webpack-dev-server/node_modules/serve-static": { "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", "dev": true, "license": "MIT", "dependencies": { @@ -22781,6 +23475,8 @@ }, "node_modules/webpack-dev-server/node_modules/type-is": { "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "license": "MIT", "dependencies": { @@ -22866,6 +23562,13 @@ "dev": true, "license": "MIT" }, + "node_modules/webpack/node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT" + }, "node_modules/webpack/node_modules/eslint-scope": { "version": "5.1.1", "dev": true, @@ -22912,6 +23615,8 @@ }, "node_modules/websocket-driver": { "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -22925,6 +23630,8 @@ }, "node_modules/websocket-extensions": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -23207,6 +23914,8 @@ }, "node_modules/wsl-utils": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/src/app/ew/fabric/FabricBaseModel.ts b/src/app/ew/fabric/FabricBaseModel.ts index 00e6162b..239c4d93 100644 --- a/src/app/ew/fabric/FabricBaseModel.ts +++ b/src/app/ew/fabric/FabricBaseModel.ts @@ -9,7 +9,7 @@ import { updatedBy, } from '@decaf-ts/core'; import { description, uses } from '@decaf-ts/decoration'; -import { hideOn, uielement } from '@decaf-ts/ui-decorators'; +import { hideOn, uielement, uiorder } from '@decaf-ts/ui-decorators'; import { OperationKeys, version } from '@decaf-ts/db-decorators'; //@uses(FabricFlavour) @@ -23,6 +23,7 @@ export class FabricBaseModel extends Model { readonly: true, }) @hideOn(OperationKeys.CREATE, OperationKeys.UPDATE) + @uiorder('last') createdAt!: Date; @column() @@ -34,6 +35,7 @@ export class FabricBaseModel extends Model { readonly: true, }) @hideOn(OperationKeys.CREATE, OperationKeys.UPDATE) + @uiorder('last') updatedAt!: Date; @column() @@ -44,6 +46,7 @@ export class FabricBaseModel extends Model { readonly: true, }) @hideOn(OperationKeys.CREATE, OperationKeys.UPDATE) + @uiorder('last') version!: number; constructor(arg?: ModelArg) { diff --git a/src/app/ew/fabric/FabricIdentifiedModel.ts b/src/app/ew/fabric/FabricIdentifiedModel.ts index b24c2044..c0dac33c 100644 --- a/src/app/ew/fabric/FabricIdentifiedModel.ts +++ b/src/app/ew/fabric/FabricIdentifiedModel.ts @@ -2,7 +2,7 @@ import { type ModelArg } from '@decaf-ts/decorator-validation'; import { column, createdBy, index, OrderDirection, updatedBy } from '@decaf-ts/core'; import { description, uses } from '@decaf-ts/decoration'; import { FabricBaseModel } from './FabricBaseModel'; -import { hideOn, uielement } from '@decaf-ts/ui-decorators'; +import { hideOn, uielement, uiorder } from '@decaf-ts/ui-decorators'; import { OperationKeys } from '@decaf-ts/db-decorators'; //@uses(FabricFlavour) @@ -16,6 +16,7 @@ export class FabricIdentifiedModel extends FabricBaseModel { readonly: true, }) @hideOn(OperationKeys.CREATE, OperationKeys.UPDATE) + @uiorder('last') createdBy!: string; @column() @@ -27,6 +28,7 @@ export class FabricIdentifiedModel extends FabricBaseModel { readonly: true, }) @hideOn(OperationKeys.CREATE, OperationKeys.UPDATE) + @uiorder('last') updatedBy!: string; constructor(arg?: ModelArg) { super(arg); diff --git a/src/app/ew/fabric/Product.ts b/src/app/ew/fabric/Product.ts index 6580b742..4a5e950b 100644 --- a/src/app/ew/fabric/Product.ts +++ b/src/app/ew/fabric/Product.ts @@ -1,5 +1,5 @@ import type { Model, ModelArg } from '@decaf-ts/decorator-validation'; -import { model, required, type } from '@decaf-ts/decorator-validation'; +import { maxlength, min, minlength, model, required, type } from '@decaf-ts/decorator-validation'; // import { gtin, TableNames } from "@pharmaledgerassoc/ptp-toolkit/shared"; import { propMetadata, Constructor } from '@decaf-ts/decoration'; @@ -38,6 +38,7 @@ import { audit } from './utils'; import { FileUploadComponent } from 'src/lib/components'; import { ProductImageHandler } from './handlers/ProductImageHandler'; import { ProductHandler } from './handlers/ProductHandler'; +import { gtin } from './gtin'; // @BlockOperations([OperationKeys.DELETE]) //@uses(FabricFlavour) @@ -46,14 +47,15 @@ import { ProductHandler } from './handlers/ProductHandler'; @uilayout('ngx-decaf-crud-form', true, 1, { empty: { showButton: false } }) @model() export class Product extends Cacheable { - //@gtin() // //@cache() // @assignProductOwner() @audit() @pk({ type: String, generated: false }) + @gtin(['errors.gtin.digits', 'errors.gtin.checksum', 'errors.gtin.fallback']) @uilistprop('title') @uielement('ngx-decaf-crud-field', { label: 'product.productCode.label', + updateOn: 'change', placeholder: 'product.productCode.placeholder', // readonly: () => { // return (this as unknown as CrudFieldComponent).operation !== OperationKeys.CREATE; @@ -73,6 +75,7 @@ export class Product extends Cacheable { }) @uilistprop('title') @uilayoutprop(2) + @minlength(2) inventedName!: string; //@cache() diff --git a/src/app/ew/fabric/gtin.ts b/src/app/ew/fabric/gtin.ts new file mode 100644 index 00000000..0e5e2f90 --- /dev/null +++ b/src/app/ew/fabric/gtin.ts @@ -0,0 +1,146 @@ +import { apply } from '@decaf-ts/decoration'; +import { + innerValidationDecorator, + validator, + ValidatorOptions, +} from '@decaf-ts/decorator-validation'; +import { UIValidator } from '@decaf-ts/ui-decorators'; + +const GTIN_VALIDATION_KEY = 'gtin'; +export const GTIN_MISSING_DIGITS_ERROR_MESSAGE = + 'Gtin length is 14. you are missing {0} more digits'; +export const GTIN_NEXT_DIGIT_ERROR_MESSAGE = 'to be a valid gtin your next digit must be {0}'; +export const GTIN_VALIDATION_ERROR_MESSAGE = 'Not a valid Gtin'; + +export function generateGtin(): string { + function pad(num: number, width: number, padding: string = '0') { + const n = num + ''; + return n.length >= width ? n : new Array(width - n.length + 1).join(padding) + n; + } + + const beforeChecksum = pad(Math.floor(Math.random() * 9999999999999), 13); // has to be 13. the checksum is the 4th digit + const checksum = calculateGtinCheckSum(beforeChecksum); + return `${beforeChecksum}${checksum}`; +} + +// https://www.gs1.org/services/how-calculate-check-digit-manually +function calculateGtinCheckSum(digits: string): string { + digits = '' + digits; + if (digits.length !== 13) throw new Error('needs to received 13 digits'); + const multiplier = [3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3]; + let sum = 0; + try { + // multiply each digit for its multiplier according to the table + for (let i = 0; i < 13; i++) sum += parseInt(digits.charAt(i)) * multiplier[i]; + + // Find the nearest equal or higher multiple of ten + const remainder = sum % 10; + let nearest; + if (remainder === 0) nearest = sum; + else nearest = sum - remainder + 10; + + return nearest - sum + ''; + } catch (e) { + throw new Error(`Did this received numbers? ${e}`); + } +} + +type MessageSource = string | string[] | undefined; + +@validator(GTIN_VALIDATION_KEY) +export class GtinValidator extends UIValidator { + constructor(message: string = GTIN_VALIDATION_ERROR_MESSAGE) { + super(message, 'string', 'number'); + } + + private resolveMessages(message?: MessageSource): [string, string, string] { + if (Array.isArray(message)) { + const [missingDigits, nextDigit, fallback] = message; + return [ + missingDigits ?? GTIN_MISSING_DIGITS_ERROR_MESSAGE, + nextDigit ?? missingDigits ?? GTIN_NEXT_DIGIT_ERROR_MESSAGE, + fallback ?? nextDigit ?? missingDigits ?? this.message, + ]; + } + if (typeof message === 'string' && message.length > 0) { + return [message, message, message]; + } + return [GTIN_MISSING_DIGITS_ERROR_MESSAGE, GTIN_NEXT_DIGIT_ERROR_MESSAGE, this.message]; + } + + hasErrors(value: number | string, options: ValidatorOptions): string | undefined { + if (value === undefined || value === null) return; + if (typeof value !== 'string' && typeof value !== 'number') { + return this.getMessage(this.message); + } + + const [missingDigitsMessage, checksumMessage, fallbackMessage] = this.resolveMessages( + options?.message || this.message, + ); + + const gtin = `${value}`.trim(); + if (!gtin) return this.getMessage(fallbackMessage); + + if (!/^\d+$/.test(gtin)) { + return this.getMessage(fallbackMessage); + } + + const length = gtin.length; + + if (length < 13) { + return this.getMessage(missingDigitsMessage, 14 - length); + } + + if (length === 13) { + const checksum = calculateGtinCheckSum(gtin); + return this.getMessage(checksumMessage, checksum); + } + + if (length > 14) { + return this.getMessage(fallbackMessage); + } + const digits = gtin.slice(0, 13); + const checksum = calculateGtinCheckSum(digits); + return checksum === gtin.charAt(13) ? undefined : this.getMessage(fallbackMessage); + } +} + +// hasErrors(value: number | string, options?: ValidatorOptions): string | undefined { +// if (value === undefined) return; + +// const { message } = options || {}; +// const [digitsError, checkSumError, fallbackError] = message as unknown as string[]; +// const gtin = value + ''; + +// let checksum: string; + +// const length = gtin.length; +// if (length > 14) return this.getMessage(fallbackError); +// if (length < 13) return this.getMessage(digitsError, length); +// if (length === 13) { +// checksum = calculateGtinCheckSum(gtin); +// return this.getMessage(checkSumError, checksum); +// } + +// if (!gtin.match(/\d{14}/g)) return this.getMessage(fallbackError || this.message); +// const digits = gtin.slice(0, 13); +// checksum = calculateGtinCheckSum(digits); +// return parseInt(checksum) === parseInt(gtin.charAt(13)) +// ? undefined +// : this.getMessage(message || this.message); +// } + +export const gtin = ( + messages: string[] = [ + GTIN_MISSING_DIGITS_ERROR_MESSAGE, + GTIN_NEXT_DIGIT_ERROR_MESSAGE, + GTIN_VALIDATION_ERROR_MESSAGE, + ], +) => { + return apply( + innerValidationDecorator(gtin, GTIN_VALIDATION_KEY, { + message: messages, + async: false, + }), + ); +}; diff --git a/src/app/utils/FakerRepository.ts b/src/app/utils/FakerRepository.ts index bcdbc54a..727cf495 100644 --- a/src/app/utils/FakerRepository.ts +++ b/src/app/utils/FakerRepository.ts @@ -11,6 +11,8 @@ import { Audit } from '../ew/fabric/Audit'; import { AuditOperations, UserGroup } from '../ew/fabric/constants'; import { ProductStrength } from '../ew/fabric/ProductStrength'; import { getModelAndRepository } from 'src/lib/engine/helpers'; +import { generate } from 'rxjs'; +import { generateGtin } from '../ew/fabric/gtin'; enum ProductNames { aspirin = 'Aspirin', ibuprofen = 'Ibuprofen', @@ -38,6 +40,30 @@ enum ProductNames { // furosemide = "Furosemide" } +async function getProducts(): Promise { + const repo = getModelAndRepository('Product'); + if (repo) { + const { repository } = repo; + const query = await repository.select().execute(); + if (query.length) { + return query as Product[]; + } + } + return []; +} + +async function getBatchs(): Promise { + const repo = getModelAndRepository('Batch'); + if (repo) { + const { repository } = repo; + const query = await repository.select().execute(); + if (query.length) { + return query as Batch[]; + } + } + return []; +} + export class FakerRepository extends DecafFakerRepository { public override async initialize(): Promise { await super.initialize(); @@ -65,9 +91,11 @@ export class FakerRepository extends DecafFakerRepository { } case Product.name: { this.limit = 2; + this.propFnMapper = { + productCode: () => generateGtin(), + }; data = (await this.generateData(ProductNames, 'inventedName', 'string')).map( (item: Partial, index: number) => { - item.productCode = index === 1 ? '00000000000013' : `0${index + 1}`.padStart(14, '0'); delete item?.['imageData']; item.markets = []; item.strengths = []; @@ -77,22 +105,16 @@ export class FakerRepository extends DecafFakerRepository { break; } case Batch.name: { - const repo = getModelAndRepository('Product'); + const products = await getProducts(); this.limit = 2; data = await this.generateData(); data = [ ...(await Promise.all( data.map(async (item: Partial, index: number) => { - const productCode = '00000000000013'; - // this.limit === 1 - // ? '00000000000013' - // : `0${Math.floor(Math.random() * 5) + 1}`.padStart(14, '0'); - const repo = getModelAndRepository('Product'); + const productCode = this.pickRandomValue(products.map((p) => p.productCode)); + const product = products.find((p) => p.productCode === productCode); item.productCode = productCode; - if (repo) { - const { repository } = repo; - const product = (await repository.read(productCode)) as Product; - } + item.batchNumber = `bt_${productCode}_${index % 2 === 0 ? 'aspirin' : this.pickRandomValue(Object.values(ProductNames))}`.trim(); // item.batchNumber = `bt_${productCode}_${item['nameMedicinalProduct']}`.trim(); @@ -109,29 +131,14 @@ export class FakerRepository extends DecafFakerRepository { break; } case Leaflet.name: { + const products = await getProducts(); this.limit = 2; this.propFnMapper = { + productCode: () => this.pickRandomValue(products.map((p) => p.productCode)), lang: () => this.pickRandomValue(['en', 'pt-br']), - productCode: () => { - const productCode = `013`; - return productCode.padStart(14, '0'); - }, epiMarket: () => this.pickRandomValue(['al', 'br']), }; - const repo = getModelAndRepository('Batch'); - let batches = [] as { batchNumber: string; productCode: string }[]; - if (repo) { - const { repository } = repo; - const query = (await repository.select().execute()) as Batch[]; - if (query.length) - batches = query.map((item) => { - return { - batchNumber: item.batchNumber, - productCode: item.productCode, - }; - }); - } - const products = batches.map((b) => b.productCode); + let batches = await getBatchs(); data = (await this.generateData()).map((item) => { // item.epiMarket = this.pickRandomValue([... getMarkets().map(({value}) => value)]); item.leafletType = this.pickRandomValue(LeafletType) as LeafletType; @@ -144,17 +151,19 @@ export class FakerRepository extends DecafFakerRepository { break; } case ProductStrength.name: { + const products = await getProducts(); this.limit = 2; data = await this.generateData(); data = data.map((item: Partial, index: number) => { - item['productCode'] = index % 2 === 0 ? '00000000000012' : '00000000000013'; + item['productCode'] = + index % 2 === 0 ? products[0].productCode : products[1].productCode; item.substance = this.pickRandomValue(ProductNames); return item as T; }) as T[]; break; } default: - data = await this.generateData(); + data = []; } try { // data = await Promise.all(data.map(async (item: Partial) => { diff --git a/src/assets/i18n/ew/en.json b/src/assets/i18n/ew/en.json index 30dc11fd..1f92ac0a 100644 --- a/src/assets/i18n/ew/en.json +++ b/src/assets/i18n/ew/en.json @@ -1,4 +1,11 @@ { + "errors": { + "gtin": { + "digits": "Gtin length is 14. you are missing {0} more digits.", + "checksum": "To be a valid gtin your next digit must be {0}", + "fallback": "Not a valid Gtin." + } + }, "component": { "modal_diffs": { "property": "Property", diff --git a/src/lib/components/crud-field/crud-field.component.html b/src/lib/components/crud-field/crud-field.component.html index 4d57b390..8c7c2f6a 100644 --- a/src/lib/components/crud-field/crud-field.component.html +++ b/src/lib/components/crud-field/crud-field.component.html @@ -43,8 +43,8 @@ > @if (type === HTML5InputTypes.TEXTAREA) { } @else { + + } diff --git a/src/lib/components/crud-field/crud-field.component.scss b/src/lib/components/crud-field/crud-field.component.scss index 59b5c5d5..b86a39c0 100644 --- a/src/lib/components/crud-field/crud-field.component.scss +++ b/src/lib/components/crud-field/crud-field.component.scss @@ -201,6 +201,7 @@ ion-radio-group { &.dcf-options-error { position: relative; margin-bottom: 0.25rem !important; + max-width: 200px !important; } .ti, ngx-decaf-icon, diff --git a/src/lib/components/crud-field/crud-field.component.spec.ts b/src/lib/components/crud-field/crud-field.component.spec.ts index fb2ff6aa..6d5c3001 100644 --- a/src/lib/components/crud-field/crud-field.component.spec.ts +++ b/src/lib/components/crud-field/crud-field.component.spec.ts @@ -1,13 +1,14 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { CrudFieldComponent } from './crud-field.component'; import { FormControl, FormGroup } from '@angular/forms'; -import { AngularFieldDefinition } from '../../engine'; -import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { ForAngularCommonModule } from '../../for-angular-common.module'; -import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { OperationKeys } from '@decaf-ts/db-decorators'; +import { CrudFieldComponent } from './crud-field.component'; +import { AngularFieldDefinition } from '../../engine/types'; +import { NgxTranslateService } from '../../services/NgxTranslateService'; +import { ForAngularCommonModule } from '../../for-angular-common.module'; import { NgxFormService } from '../../services/NgxFormService'; -import { By } from '@angular/platform-browser'; import { I18nFakeLoader, MockedEnTranslations } from '../../i18n/FakeLoader'; const imports = [ @@ -21,7 +22,10 @@ const imports = [ }), ]; -async function getErrorMessage(fixture: ComponentFixture, selector: string = 'ion-input'): Promise { +async function getErrorMessage( + fixture: ComponentFixture, + selector: string = 'ion-input', +): Promise { const ionInput = fixture.debugElement.query(By.css(selector)).componentInstance; await ionInput.getInputElement(); const errorText = ionInput.errorText; @@ -30,25 +34,27 @@ async function getErrorMessage(fixture: ComponentFixture, se return errorElement?.textContent || errorText; } -function updateFieldValidators(fixture: ComponentFixture, component: CrudFieldComponent): void { - fixture.detectChanges(); - const validators = NgxFormService['validatorsFromProps'](component); - component.formControl = new FormControl(component.value, validators); - component.formGroup = new FormGroup({ - [component.name]: component.formControl, - }); - component.formGroup.get(component.name)?.markAsTouched(); - component.formGroup.get(component.name)?.markAsDirty(); - - fixture.detectChanges(); +function updateFieldValidators( + fixture: ComponentFixture, + component: CrudFieldComponent, +): void { + fixture.detectChanges(); + const validators = NgxFormService['validatorsFromProps'](component); + component.formControl = new FormControl(component.value, validators); + component.formGroup = new FormGroup({ + [component.name]: component.formControl, + }); + component.formGroup.get(component.name)?.markAsTouched(); + component.formGroup.get(component.name)?.markAsDirty(); + fixture.detectChanges(); } describe('CrudFieldComponent', () => { let component: CrudFieldComponent; let fixture: ComponentFixture; // let formBuilder: FormBuilder; - let translateService: TranslateService; + let translateService: NgxTranslateService; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -56,7 +62,7 @@ describe('CrudFieldComponent', () => { schemas: [CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); - translateService = TestBed.inject(TranslateService); + translateService = TestBed.inject(NgxTranslateService); fixture = TestBed.createComponent(CrudFieldComponent); component = fixture.componentInstance; translateService = component['translateService']; @@ -74,7 +80,7 @@ describe('CrudFieldComponent', () => { expect(component).toBeTruthy(); }); - const testCases: { type: string; selector: string, value: any }[] = [ + const testCases: { type: string; selector: string; value: any }[] = [ { type: 'textarea', selector: 'ion-textarea', value: 'textarea value' }, { type: 'checkbox', selector: 'ion-checkbox', value: 'checkbox value' }, { type: 'radio', selector: 'ion-radio-group', value: 'checkbox value' }, @@ -107,19 +113,17 @@ describe('CrudFieldComponent', () => { }); component.translatable = false; - Object.entries(props).forEach(([key, value]) => (component as any)[key] = value); + Object.entries(props).forEach(([key, value]) => ((component as any)[key] = value)); // component.props = props; fixture.detectChanges(); const element = fixture.nativeElement.querySelector(selector); expect(element).toBeTruthy(); if (type === 'radio') { - const radioButtons = - fixture.nativeElement.querySelectorAll('ion-radio'); + const radioButtons = fixture.nativeElement.querySelectorAll('ion-radio'); expect(radioButtons.length).toBe(2); } else if (type === 'select') { - const options = - fixture.nativeElement.querySelectorAll('ion-select-option'); + const options = fixture.nativeElement.querySelectorAll('ion-select-option'); expect(options.length).toBe(2); } }); @@ -162,7 +166,6 @@ describe('CrudFieldComponent', () => { }); it('should show error message when pattern is not matched', async () => { - component.label = 'Pattern Field'; component.pattern = '^[A-Za-z]+$'; component.value = '123'; @@ -174,7 +177,7 @@ describe('CrudFieldComponent', () => { expect(errorMessage).toContain('pattern'); }); - it('should show error message when min value is not met', async() => { + it('should show error message when min value is not met', async () => { component.type = 'number'; component.label = 'Min Field'; component.min = 5; @@ -195,7 +198,6 @@ describe('CrudFieldComponent', () => { const errorMessage = await getErrorMessage(fixture); expect(component.formControl.errors?.['max']).toBeTruthy(); expect(errorMessage).toContain('max'); - }); it('should not show error message when field is valid', async () => { @@ -216,7 +218,6 @@ describe('CrudFieldComponent', () => { // return key; // }); - fixture.detectChanges(); component.label = MockedEnTranslations.FIELD_LABEL; component.placeholder = MockedEnTranslations.FIELD_PLACEHOLDER; @@ -241,8 +242,10 @@ describe('CrudFieldComponent', () => { updateFieldValidators(fixture, component); - const input = fixture.nativeElement.querySelector('ion-input') || fixture.nativeElement.querySelector('ion-item'); - if(input.tagName.toLowerCase() === 'ion-input') { + const input = + fixture.nativeElement.querySelector('ion-input') || + fixture.nativeElement.querySelector('ion-item'); + if (input.tagName.toLowerCase() === 'ion-input') { expect(input.readonly).toBeTruthy(); } else { expect(input.classList.contains('dcf-item-readonly')).toBeTruthy(); @@ -254,8 +257,7 @@ describe('CrudFieldComponent', () => { component.value = ''; fixture.detectChanges(); - if (!component.formGroup) - component.formGroup = new FormGroup({}); + if (!component.formGroup) component.formGroup = new FormGroup({}); component.formGroup.disable(); const input = fixture.nativeElement.querySelector('ion-input'); diff --git a/src/lib/components/crud-field/crud-field.component.ts b/src/lib/components/crud-field/crud-field.component.ts index 5adc4a52..a2405e94 100644 --- a/src/lib/components/crud-field/crud-field.component.ts +++ b/src/lib/components/crud-field/crud-field.component.ts @@ -58,6 +58,7 @@ import { getNgxSelectOptionsModal } from '../modal/modal.component'; import { ActionRoles, SelectFieldInterfaces } from '../../engine/constants'; import { IconComponent } from '../icon/icon.component'; import { getModelAndRepository } from '../../engine/helpers'; +import { Validator } from '@decaf-ts/decorator-validation'; /** * @description A dynamic form field component for CRUD operations. @@ -202,6 +203,12 @@ export class CrudFieldComponent @Input({ required: true }) override type!: PossibleInputTypes; + @Input() + subType!: PossibleInputTypes; + + @Input() + validationMessage?: string | string[]; + /** * @description The initial value of the field. * @summary Sets the initial value of the form field. This can be a string, number, or Date @@ -557,7 +564,6 @@ export class CrudFieldComponent * @summary Determines the fill style of the field, such as 'outline' or 'solid'. * This affects the border and background of the field. * - * @type {'outline' | 'solid'} * @default 'outline' * @memberOf CrudFieldComponent */ diff --git a/src/lib/components/table/table.component.ts b/src/lib/components/table/table.component.ts index 89708113..5635720f 100644 --- a/src/lib/components/table/table.component.ts +++ b/src/lib/components/table/table.component.ts @@ -3,9 +3,9 @@ import { CommonModule } from '@angular/common'; import { TranslatePipe } from '@ngx-translate/core'; import { IonSelect, IonSelectOption } from '@ionic/angular/standalone'; import { OrderDirection } from '@decaf-ts/core'; -import { Model } from '@decaf-ts/decorator-validation'; +import { Model, Primitives } from '@decaf-ts/decorator-validation'; import { CrudOperations, OperationKeys } from '@decaf-ts/db-decorators'; -import { ComponentEventNames, UIFunctionLike } from '@decaf-ts/ui-decorators'; +import { ComponentEventNames, UIFunctionLike, UIKeys } from '@decaf-ts/ui-decorators'; import { SearchbarComponent } from '../searchbar/searchbar.component'; import { IconComponent } from '../icon/icon.component'; import { PaginationComponent } from '../pagination/pagination.component'; @@ -69,7 +69,25 @@ export class TableComponent extends ListComponent implements OnInit { private get _cols(): string[] { this.mapper = this._mapper; return Object.entries(this.mapper) - .sort(([, a], [, b]) => Number(a?.['sequence'] ?? 0) - Number(b?.['sequence'] ?? 0)) + .sort(([, a], [, b]) => { + const aSequence = a?.sequence ?? 0; + const bSequence = b?.sequence ?? 0; + const weight = (v: string | number) => + v === UIKeys.FIRST ? 0 : typeof v === Primitives.NUMBER ? 1 : v === UIKeys.LAST ? 100 : 1; + const aWeight = weight(aSequence); + const bWeight = weight(bSequence); + if (aWeight !== bWeight) { + return aWeight - bWeight; + } + if ( + aWeight === 1 && + typeof aSequence === Primitives.NUMBER && + typeof bSequence === Primitives.NUMBER + ) { + return aSequence - bSequence; + } + return 0; + }) .map(([key]) => key); } diff --git a/src/lib/engine/NgxComponentDirective.ts b/src/lib/engine/NgxComponentDirective.ts index bf32a308..33ef560c 100644 --- a/src/lib/engine/NgxComponentDirective.ts +++ b/src/lib/engine/NgxComponentDirective.ts @@ -26,8 +26,7 @@ import { } from '@angular/core'; import { NavigationStart, Router } from '@angular/router'; import { Location } from '@angular/common'; -import { TranslateService } from '@ngx-translate/core'; -import { firstValueFrom, shareReplay, Subject, takeUntil } from 'rxjs'; +import { shareReplay, Subject, takeUntil } from 'rxjs'; import { Model, ModelConstructor, ModelKeys, Primitives } from '@decaf-ts/decorator-validation'; import { CrudOperations, InternalError, OperationKeys } from '@decaf-ts/db-decorators'; import { ComponentEventNames, DecafEventHandler } from '@decaf-ts/ui-decorators'; @@ -51,6 +50,7 @@ import { LoadingController, LoadingOptions } from '@ionic/angular/standalone'; import { OverlayBaseController } from '@ionic/angular/common'; import { getModelAndRepository } from './helpers'; import { NgxRepositoryDirective } from './NgxRepositoryDirective'; +import { NgxTranslateService } from '../services/NgxTranslateService'; try { const win = getWindow(); @@ -354,10 +354,10 @@ export abstract class NgxComponentDirective * Used to translate button labels, validation messages, and other text content based * on the current locale setting, enabling multilingual support throughout the application. * @protected - * @type {TranslateService} + * @type {NgxTranslateService} * @memberOf module:lib/engine/NgxComponentDirective */ - protected translateService: TranslateService = inject(TranslateService); + override translateService: NgxTranslateService = inject(NgxTranslateService); /** * @description Event emitter for custom component events. @@ -760,9 +760,7 @@ export abstract class NgxComponentDirective * @memberOf module:lib/engine/NgxComponentDirective */ override async translate(phrase: string | string[], params?: object | string): Promise { - if (!phrase) return ''; - if (typeof params === Primitives.STRING) params = { '0': params }; - return await firstValueFrom(this.translateService.get(phrase, (params || {}) as object)); + return await this.translateService.get(phrase, params || {}); } protected checkDarkMode(): void { @@ -1037,9 +1035,9 @@ export abstract class NgxComponentDirective } // passed for ui decorators - override async submit(...args: unknown[]): Promise { - this.log.for(this.submit).info(`submit for ${this.componentName} with ${JSON.stringify(args)}`); - } + // override async submit(...args: unknown[]): Promise { + // this.log.for(this.submit).info(`submit for ${this.componentName} with ${JSON.stringify(args)}`); + // } /** * @description Determines if a specific operation is allowed in the current context. diff --git a/src/lib/engine/NgxFormFieldDirective.ts b/src/lib/engine/NgxFormFieldDirective.ts index 669e68d6..70022b6d 100644 --- a/src/lib/engine/NgxFormFieldDirective.ts +++ b/src/lib/engine/NgxFormFieldDirective.ts @@ -5,23 +5,28 @@ * and FieldProperties to enable form field integration with Angular's reactive forms system. * This directive handles form control lifecycle, validation, multi-entry forms, and CRUD operations. */ +import { Directive, Inject, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { + AbstractControl, + ControlValueAccessor, + FormArray, + FormControl, + FormGroup, +} from '@angular/forms'; +import { sf } from '@decaf-ts/logging'; +import { Primitives } from '@decaf-ts/decorator-validation'; +import { CrudOperations, InternalError, OperationKeys } from '@decaf-ts/db-decorators'; +import { ComponentEventNames, UIValidator } from '@decaf-ts/ui-decorators'; import { FieldProperties, HTML5InputTypes, RenderingError, UIEventProperty, } from '@decaf-ts/ui-decorators'; -import { FormParent, KeyValue, PossibleInputTypes } from './types'; -import { CrudOperations, InternalError, OperationKeys } from '@decaf-ts/db-decorators'; -import { ControlValueAccessor, FormArray, FormControl, FormGroup } from '@angular/forms'; -import { Directive, Inject, Input, OnChanges, SimpleChanges } from '@angular/core'; -import { NgxFormService } from '../services/NgxFormService'; -import { sf } from '@decaf-ts/decorator-validation'; -import { ComponentEventNames } from '@decaf-ts/ui-decorators'; - -import { FunctionLike } from './types'; import { NgxComponentDirective } from './NgxComponentDirective'; -import { CPTKN } from './constants'; +import { NgxFormService } from '../services/NgxFormService'; +import { FormParent, FunctionLike, KeyValue, PossibleInputTypes } from './types'; +import { CPTKN, AngularEngineKeys } from './constants'; import { SelectCustomEvent } from '@ionic/angular/standalone'; /** @@ -255,6 +260,22 @@ export abstract class NgxFormFieldDirective */ multiple!: boolean; + /** + * @description Custom type definitions for field validation. + * @summary Allows specifying custom types beyond HTML5 input types to support specialized validation logic. + * Can be a single type string or an array of type strings for multi-type validation scenarios. + * @type {string | string[] | undefined} + * @public + */ + customTypes?: string | string[] | undefined; + + /** + * @description Whether the field is currently checked. + * @summary Used for checkbox and radio button fields to track the checked state independently from the value. + * @type {boolean} + * @default false + * @public + */ checked: boolean = false; /** @@ -288,10 +309,10 @@ export abstract class NgxFormFieldDirective // eslint-disable-next-line @angular-eslint/prefer-inject constructor(@Inject(CPTKN) componentName: string = 'ComponentCrudField') { super(componentName); + if (!UIValidator.translateService) { + UIValidator.translateService = this.translateService; + } } - maxLength?: number | undefined; - minLength?: number | undefined; - customTypes?: string | string[] | undefined; /** * @description Gets the currently active form group based on context. @@ -507,12 +528,59 @@ export abstract class NgxFormFieldDirective * @return {void} * @public */ - handleModalChildChanges(event?: SelectCustomEvent): void { + handleModalChildChanges(event?: SelectCustomEvent, formControl?: AbstractControl): void { + const element = this.component?.nativeElement; if (this.type === HTML5InputTypes.SELECT && event) { const { value } = event.detail; this.value = value; } - if (this.isModalChild) this.changeDetectorRef.detectChanges(); + if (element && formControl && !formControl.valid && formControl.updateOn === 'change') { + element.dispatchEvent(new Event('ionBlur')); + } + if (this.isModalChild) { + this.changeDetectorRef.detectChanges(); + } + } + + private validateControl(formControl: AbstractControl): boolean { + return ( + (!formControl.valid && (formControl.touched || !formControl.pristine)) || + (!formControl.valid && formControl.dirty && formControl.updateOn === 'change') + ); + } + + private getErrorMessage(error: Record): string { + const instance = this as KeyValue; + let { message, key } = error; + const prop = instance[key]; + let args = [] as string[]; + if (typeof message === Primitives.STRING) { + if (message.includes('|')) { + const parts = message.split('|'); + message = parts[0]; + parts.shift(); + parts.forEach((part) => { + args = [...args, part]; + }); + } else { + if (prop) { + args = [prop]; + } + } + } else { + args = Object.values(message).map((v) => `${v || prop}`) as string[]; + message = key; + } + // Check if string already be translated by validator + const translate = (message: string, args: string[]): string => { + return this.translateService.instant( + !message.includes(AngularEngineKeys.ERRORS) + ? `${AngularEngineKeys.ERRORS}.${message}` + : message, + args, + ); + }; + return /\s/.test(message) && message !== key ? message : translate(message, args); } /** @@ -530,12 +598,16 @@ export abstract class NgxFormFieldDirective const accordionComponent = parent .closest('ngx-decaf-fieldset') ?.querySelector('ion-accordion-group'); - if ((!formControl.pristine || formControl.touched) && !formControl.valid) { - const errors: Record[] = Object.keys(formControl.errors ?? {}).map( - (key) => ({ - key: key, - message: key, - }), + const invalid = this.validateControl(formControl); + if (invalid) { + const errors: Record[] = Object.entries(formControl.errors ?? {}).map( + ([key, value]) => { + const message = typeof value === 'boolean' ? key : value; + return { + key: key, + message, + }; + }, ); if (errors.length) { if (accordionComponent && !this.validationErrorEventDispatched) { @@ -548,8 +620,7 @@ export abstract class NgxFormFieldDirective } } for (const error of errors) { - const instance = this as KeyValue; - return `* ${this.translateService.instant(`errors.${error?.['message']}`, { '0': `${instance[error?.['key']] ?? ''}` })}`; + return `* ${this.getErrorMessage(error)}`; } } } diff --git a/src/lib/engine/NgxRenderingEngine.ts b/src/lib/engine/NgxRenderingEngine.ts index 3e8f743e..aeb104fc 100644 --- a/src/lib/engine/NgxRenderingEngine.ts +++ b/src/lib/engine/NgxRenderingEngine.ts @@ -210,17 +210,15 @@ export class NgxRenderingEngine extends RenderingEngine< const { inputs: possibleInputs } = componentMetadata; const inputs = { ...fieldDef.props }; - const unmappedKeys = Object.keys(inputs).filter((input) => { - const isMapped = possibleInputs.find(({ propName }) => propName === input); - if (!isMapped) delete inputs[input]; - return !isMapped; - }); - + // const unmappedKeys = Object.keys(inputs).filter((input) => { + // const isMapped = possibleInputs.find(({ propName }) => propName === input); + // if (!isMapped) delete inputs[input]; + // return !isMapped; + // }); // if (unmappedKeys.length > 0 && isDevelopmentMode()) // getLogger(this).warn( // `Unmapped input properties for component ${fieldDef.tag}: ${unmappedKeys.join(', ')}`, // ); - const operation = NgxRenderingEngine._operation; const hiddenOn = inputs?.hidden || []; diff --git a/src/lib/engine/NgxRepositoryDirective.ts b/src/lib/engine/NgxRepositoryDirective.ts index c62045d4..e2d1a37f 100644 --- a/src/lib/engine/NgxRepositoryDirective.ts +++ b/src/lib/engine/NgxRepositoryDirective.ts @@ -12,6 +12,7 @@ import { DecafRepository, KeyValue } from './types'; import { Constructor, Metadata } from '@decaf-ts/decoration'; import { IFilterQuery } from './interfaces'; import { Subject } from 'rxjs'; +import { getModelAndRepository } from './helpers'; @Directive() export class NgxRepositoryDirective extends DecafComponent { @@ -248,6 +249,12 @@ export class NgxRepositoryDirective extends DecafComponent { attr = (this.filterBy || this.pk) as keyof M; } const condition = this.filter || Condition.attribute(attr); + if (!this.repository) { + const repo = getModelAndRepository(Model.tableName(this.model as Model)); + if (repo) { + this._repository = repo.repository as DecafRepository; + } + } const type = this.getModelPropertyType(this.repository.class, attr as keyof M); if (this.modelId) { return condition.eq( @@ -438,8 +445,18 @@ export class NgxRepositoryDirective extends DecafComponent { return Metadata.properties(clazz) as (keyof M)[]; } - protected getModelPropertyType(constructor: Constructor, prop: keyof M): string { - return Metadata.type(constructor as Constructor, prop as string).name; + protected getModelPropertyType(constructor: Constructor | string, prop: keyof M): string { + try { + return Metadata.type(constructor as Constructor, prop as string)?.name; + } catch (error: unknown) { + this.log + .for(this) + .info(`${(error as Error)?.message || String(error)}. Tryng get with table Name`); + constructor = Model.get( + Model.tableName(this.repository.class as Constructor) as string, + ) as Constructor; + return Metadata.type(constructor, prop as string)?.name; + } } protected getModelPkType(clazz: Constructor): string { diff --git a/src/lib/engine/ValidatorFactory.ts b/src/lib/engine/ValidatorFactory.ts index 3f7039a2..75a29dfe 100644 --- a/src/lib/engine/ValidatorFactory.ts +++ b/src/lib/engine/ValidatorFactory.ts @@ -7,10 +7,15 @@ * * @link {@link ValidatorFactory} */ -import { AbstractControl, FormControl, FormGroup, ValidationErrors, ValidatorFn } from '@angular/forms'; +import { + AbstractControl, + FormControl, + FormGroup, + ValidationErrors, + ValidatorFn, +} from '@angular/forms'; import { ComparisonValidationKeys, - DEFAULT_PATTERNS, PathProxy, PathProxyEngine, Primitives, @@ -18,87 +23,106 @@ import { ValidationKeys, Validator, } from '@decaf-ts/decorator-validation'; -import { FieldProperties, HTML5InputTypes, parseValueByType } from '@decaf-ts/ui-decorators'; -import { AngularEngineKeys } from './constants'; -import { KeyValue } from './types'; +import { + FieldProperties, + HTML5InputTypes, + parseValueByType, + UIKeys, +} from '@decaf-ts/ui-decorators'; import { NgxRenderingEngine } from './NgxRenderingEngine'; - - -type ComparisonValidationKey = typeof ComparisonValidationKeys[keyof typeof ComparisonValidationKeys]; - -/** - * - * Resolves the correct validator key and its associated properties based on the input key and type. - * - * When the validation key is TYPE, it's necessary to resolve the actual validator based on the - * field's type (e.g., 'password', 'email', 'url') instead of using the generic getValidator("type") logic. - * This allows directly invoking specific validators like getValidator('password'), ensuring the correct - * behavior for type-based validation. - * - * @param key - The validation key (e.g., 'type', 'required', etc.). - * @param value - The value that needs be provided to the validator. - * @param type - The field's declared type. - * @returns An object containing the resolved validator key and its corresponding props. - */ -const resolveValidatorKeyProps = (key: string, value: unknown, type: string): { - validatorKey: string; - props: Record; -} => { - const patternValidators: Record = { - [ValidationKeys.PASSWORD]: DEFAULT_PATTERNS.PASSWORD.CHAR8_ONE_OF_EACH, - [ValidationKeys.EMAIL]: DEFAULT_PATTERNS.EMAIL, - [ValidationKeys.URL]: DEFAULT_PATTERNS.URL, - }; - const isTypeBased = key === ValidationKeys.TYPE && Object.keys(patternValidators).includes(type); - const validatorKey = isTypeBased ? type : key; - if (key === ValidationKeys.TYPE && HTML5InputTypes.CHECKBOX && value !== type ) - value = type; - const props: Record = { - // [validatorKey]: (!isTypeBased && key === 'type') ? parseType(type) : value, - [validatorKey]: (!isTypeBased && validatorKey === ValidationKeys.TYPE) ? NgxRenderingEngine.get().translate(value as string, false) : value, - // Email, Password, and URL are validated using the "pattern" key - ...(isTypeBased && { [ValidationKeys.PATTERN] : patternValidators[type] }), - }; - - return { validatorKey, props }; -}; - +import { ComparisonValidationKey, KeyValue } from './types'; +import { getLogger } from './helpers'; +import { patternValidators } from './constants'; export class ValidatorFactory { + /** + * @summary Extracts and parses the value from an Angular control. + * @description Retrieves the control's value and converts it to the appropriate type based on field properties. + * Handles undefined values gracefully by returning undefined without parsing. + * + * @param {AbstractControl} control - The Angular form control to extract the value from. + * @param {string} fieldType - The declared type of the field. + * @param {FieldProperties} fieldProps - The field properties containing type conversion metadata. + * @returns {unknown} The parsed value or undefined if the control value is undefined. + */ + static getFieldValue( + control: AbstractControl, + fieldType: string, + fieldProps: FieldProperties, + ): unknown { + return typeof control.value !== 'undefined' + ? parseValueByType(fieldType, control.value, fieldProps) + : undefined; + } + /** + * @summary Resolves the effective field type from multiple possible type sources. + * @description Determines the field's type by checking customTypes, subType, or type in order of priority. + * For checkbox and array fields with options, converts the type to STRING for proper validation. + * + * @param {string} [type] - The primary field type. + * @param {string | string[]} [customTypes] - Custom type definition with highest priority. + * @param {unknown[]} [options] - Available options for the field (affects checkbox/array handling). + * @param {string} [subType] - Secondary type definition. + * @returns {string} The resolved field type. + */ + static getFieldType( + type?: string, + customTypes?: string | string[], + options?: unknown[], + subType?: string, + ): string { + const fieldType = (customTypes || subType || type) as string; + if ( + (fieldType === HTML5InputTypes.CHECKBOX || fieldType === Array.name) && + Array.isArray(options) + ) { + return Primitives.STRING; + } + return fieldType; + } + + /** + * @summary Creates a ValidatorFn for a specific validation key. + * @description Generates an Angular ValidatorFn that applies Decaf validation logic to a form control. + * Resolves the appropriate validator based on field type, parses the control value, constructs validation properties, + * and handles comparison validators through proxy access to parent/child form values. + * + * @param {FieldProperties} fieldProps - The field properties containing type and validation metadata. + * @param {string} key - The validation key to create a validator for. + * @returns {ValidatorFn} A validator function that returns ValidationErrors or null. + * @throws {Error} If the validation key is not supported. + */ static spawn(fieldProps: FieldProperties, key: string): ValidatorFn { - if (!Validation.keys().includes(key)) + if (!Validation.keys().includes(key)) { throw new Error('Unsupported custom validation'); - + } const validatorFn: ValidatorFn = (control: AbstractControl): ValidationErrors | null => { - const { type, customTypes, options } = fieldProps; - let fieldType = (customTypes || type) as string; - if ((fieldType === HTML5InputTypes.CHECKBOX || fieldType === Array.name) && Array.isArray(options)) - fieldType = Primitives.STRING; - - const { validatorKey, props } = resolveValidatorKeyProps(key, fieldProps[key as keyof FieldProperties], fieldType); + const { type, customTypes, options, subType } = fieldProps || {}; + const fieldType = ValidatorFactory.getFieldType(type, customTypes, options, subType); + const customValidator = key === UIKeys.TYPE && subType; + const { validatorKey, props } = this.resolveValidatorKeyProps( + key, + fieldType, + fieldProps, + customValidator ? (subType as string) : undefined, + ); const validator = Validation.get(validatorKey) as Validator; - // parseValueByType does not support undefined values - const value = typeof control.value !== 'undefined' - ? parseValueByType(fieldType, control.value, fieldProps) - : undefined; - + const value = ValidatorFactory.getFieldValue(control, fieldType, fieldProps); // Create a proxy to enable access to parent and child values - let proxy: PathProxy = ValidatorFactory.createProxy({} as AbstractControl); - if (Object.values(ComparisonValidationKeys).includes(key as ComparisonValidationKey)) { - const parent: FormGroup = control instanceof FormGroup ? control : (control as KeyValue)[AngularEngineKeys.PARENT]; - proxy = ValidatorFactory.createProxy(parent) as PathProxy; - } - + const proxy = ValidatorFactory.getValidatorProxy(control, key as ComparisonValidationKey); let errs: string | undefined; try { - + const validationMessage = fieldProps?.validationMessage; + if (validationMessage && customValidator) { + Object.assign(props, { message: validationMessage }); + } errs = validator.hasErrors(value, props, proxy); } catch (e: unknown) { errs = `${key} validator failed to validate: ${e}`; - console.error(errs); + getLogger(ValidatorFactory).error(errs); } - return errs ? { [validatorKey]: true } : null; + return errs ? { [validatorKey]: props?.['message'] ? errs : true } : null; }; Object.defineProperty(validatorFn, 'name', { @@ -108,6 +132,66 @@ export class ValidatorFactory { return validatorFn; } + /** + * Retrieves the validator value from field properties, with special handling for checkbox types. + * Returns the field property value, or the type if the field is a checkbox and the types differ. + * + * @param key - The validation key. + * @param type - The field's type. + * @param fieldProps - The field properties object. + * @returns The validator value to use. + */ + static getValidatorValue(key: string, type: string, fieldProps: FieldProperties): unknown { + return key === ValidationKeys.TYPE && + HTML5InputTypes.CHECKBOX && + fieldProps[key as keyof FieldProperties] !== type + ? type + : fieldProps[key as keyof FieldProperties]; + } + + /** + * Determines whether a validation should be resolved based on the field's type. + * Returns true for TYPE validations with custom types or pattern-based validators. + * + * @param key - The validation key to evaluate. + * @param type - The field's declared type. + * @param customTypes - Optional custom type definition. + * @returns True if validation should use type-based resolution. + */ + static isTypeBasedValidation( + key: string, + type: string, + customTypes: string | undefined, + ): boolean { + return ( + key === ValidationKeys.TYPE && + (typeof customTypes === Primitives.STRING || Object.keys(patternValidators).includes(type)) + ); + } + + /** + * @summary Creates or retrieves a proxy for validator access to parent/child form values. + * @description Returns a PathProxy configured for the given validation key. + * For comparison validators, creates a proxy rooted at the parent FormGroup to enable cross-field validation. + * For other validators, returns an empty proxy for type safety. + * + * @param {AbstractControl | FormGroup} control - The form control to create a proxy for. + * @param {ComparisonValidationKey} key - The validation key determining proxy scope. + * @returns {PathProxy} A proxy object for form value access. + */ + static getValidatorProxy( + control: AbstractControl | FormGroup, + key: ComparisonValidationKey, + ): PathProxy { + const proxy = ValidatorFactory.createProxy({} as AbstractControl); + if (Object.values(ComparisonValidationKeys).includes(key)) { + return ValidatorFactory.createProxy( + (control instanceof FormGroup ? control : control.parent) as FormGroup, + ); + } + return proxy; + } + /** * @summary Creates a proxy wrapper for an Angular AbstractControl to assist with custom validation logic. * @description Returns a structured proxy object that simulates a hierarchical tree of form values. @@ -116,11 +200,10 @@ export class ValidatorFactory { * @param {AbstractControl} control - The control to wrap in a proxy. * @returns {PathProxy} A proxy object exposing form values and enabling recursive parent access. */ - static createProxy(control: AbstractControl): PathProxy { + static createProxy(control: AbstractControl | FormGroup): PathProxy { return PathProxyEngine.create(control, { getValue(target: AbstractControl, prop: string): unknown { - if (target instanceof FormControl) - return target.value; + if (target instanceof FormControl) return target.value; if (target instanceof FormGroup) { const control = target.controls[prop]; @@ -138,11 +221,64 @@ export class ValidatorFactory { return (target as KeyValue)?.[prop]; }, - getParent: function(target: AbstractControl) { + getParent: function (target: AbstractControl) { return target?.['_parent']; }, ignoreUndefined: true, ignoreNull: true, }); } + + /** + * + * Resolves the correct validator key and its associated properties based on the input key and type. + * + * When the validation key is TYPE, it's necessary to resolve the actual validator based on the + * field's type (e.g., 'password', 'email', 'url') instead of using the generic getValidator("type") logic. + * This allows directly invoking specific validators like getValidator('password'), ensuring the correct + * behavior for type-based validation. + * + * @param key - The validation key (e.g., 'type', 'required', etc.). + * @param value - The value that needs be provided to the validator. + * @param type - The field's declared type. + * @returns An object containing the resolved validator key and its corresponding props. + */ + static resolveValidatorKeyProps = ( + key: string, + type: string, + fieldProps: FieldProperties, + customTypes: string | undefined = undefined, + ): { validatorKey: string; props: KeyValue } => { + const isTypeBased = this.isTypeBasedValidation(key, type, customTypes); + const validatorKey = isTypeBased ? type : key; + const value = this.getValidatorValue(key, type, fieldProps); + const props = this.getValidatorProps(validatorKey, type, isTypeBased, value); + return { validatorKey, props }; + }; + + /** + * Constructs the properties object to be passed to a validator. + * Handles translation of string values and applies pattern validators for type-based validations. + * + * @param validatorKey - The resolved validator key. + * @param type - The field's type. + * @param isTypeBased - Whether this is a type-based validation. + * @param value - The value to validate. + * @returns An object containing validator properties. + */ + static getValidatorProps( + validatorKey: string, + type: string, + isTypeBased: boolean, + value: unknown, + ): KeyValue { + return { + [validatorKey]: + !isTypeBased && validatorKey === ValidationKeys.TYPE + ? NgxRenderingEngine.get().translate(value as string, false) + : value, + // Email, Password, and URL are validated using the "pattern" key + ...(isTypeBased && { [ValidationKeys.PATTERN]: patternValidators[type] }), + }; + } } diff --git a/src/lib/engine/constants.ts b/src/lib/engine/constants.ts index 491af7e7..e60b931f 100644 --- a/src/lib/engine/constants.ts +++ b/src/lib/engine/constants.ts @@ -1,4 +1,8 @@ -import { VALIDATION_PARENT_KEY } from '@decaf-ts/decorator-validation'; +import { + DEFAULT_PATTERNS, + VALIDATION_PARENT_KEY, + ValidationKeys, +} from '@decaf-ts/decorator-validation'; import { I18nToken, ICrudFormOptions, IListEmptyOptions } from './interfaces'; import { ModalOptions } from '@ionic/angular/standalone'; import { OperationKeys } from '@decaf-ts/db-decorators'; @@ -7,6 +11,20 @@ import { DecafRepositoryAdapter } from './types'; export const DB_ADAPTER_FLAVOUR_TOKEN = 'DbAdapterFlavour'; +/** + * Maps validation keys for password, email, and URL to their corresponding regex patterns. + * These patterns are used to validate field values against standard format requirements. + */ +/** + * Maps validation keys for password, email, and URL to their corresponding regex patterns. + * These patterns are used to validate field values against standard format requirements. + */ +export const patternValidators: Record = { + [ValidationKeys.PASSWORD]: DEFAULT_PATTERNS.PASSWORD.CHAR8_ONE_OF_EACH, + [ValidationKeys.EMAIL]: DEFAULT_PATTERNS.EMAIL, + [ValidationKeys.URL]: DEFAULT_PATTERNS.URL, +}; + /** * @description Injection token for registering the database adapter provider. * @summary Used to inject the database adapter instance that implements DecafRepositoryAdapter. @@ -157,6 +175,7 @@ export const AngularEngineKeys = { RENDERED: 'rendered-as-', MAPPER: 'mapper', CHILDREN: 'children', + ERRORS: 'errors', LISTABLE: 'listable', RENDER: 'render', RENDERED_ID: 'rendered-as-{0}', diff --git a/src/lib/engine/helpers.ts b/src/lib/engine/helpers.ts index 05889dba..c66fff40 100644 --- a/src/lib/engine/helpers.ts +++ b/src/lib/engine/helpers.ts @@ -55,6 +55,7 @@ export function getModelAndRepository( model: M | string, clazz?: NgxComponentDirective, ): IRepositoryModelProps | undefined { + if (!model) return undefined; try { const modelName = ( typeof model === Primitives.STRING ? model : (model as Model).constructor.name diff --git a/src/lib/engine/types.ts b/src/lib/engine/types.ts index 6c0b42da..8a89ad53 100644 --- a/src/lib/engine/types.ts +++ b/src/lib/engine/types.ts @@ -12,7 +12,7 @@ import { FormArray, FormGroup } from '@angular/forms'; import { FormServiceControl, I18nResourceConfig, InputOption } from './interfaces'; import { Adapter, Repository } from '@decaf-ts/core'; import { Context, RepositoryFlags } from '@decaf-ts/db-decorators'; -import { Model } from '@decaf-ts/decorator-validation'; +import { ComparisonValidationKeys, Model } from '@decaf-ts/decorator-validation'; import { ActionRoles, ListItemPositions, WindowColorSchemes } from './constants'; import { DecafComponent, @@ -26,6 +26,13 @@ import { Constructor } from '@decaf-ts/decoration'; import { EnvironmentProviders, Provider } from '@angular/core'; import { NgxComponentDirective } from './NgxComponentDirective'; +/** + * Represents a validation key used for comparison-based validations. + * Extracted from the ComparisonValidationKeys object to ensure type safety. + */ +export type ComparisonValidationKey = + (typeof ComparisonValidationKeys)[keyof typeof ComparisonValidationKeys]; + export interface RawQuery { select: undefined | (keyof M)[]; from: Constructor; diff --git a/src/lib/services/NgxFormService.ts b/src/lib/services/NgxFormService.ts index 00832bb6..8772fbf9 100644 --- a/src/lib/services/NgxFormService.ts +++ b/src/lib/services/NgxFormService.ts @@ -995,19 +995,20 @@ export class NgxFormService { static fromProps(props: FieldProperties, updateMode: FieldUpdateMode = 'change'): FormControl { const validators = this.validatorsFromProps(props); const composed = validators.length ? Validators.compose(validators) : null; + const value = props.value + ? props.type === HTML5InputTypes.CHECKBOX + ? Array.isArray(props.value) + ? props.value + : undefined + : props.type === HTML5InputTypes.DATE + ? !isValidDate(parseDate(props.format as string, props.value as string)) + ? undefined + : props.value + : (props.value as KeyValue) + : undefined; return new FormControl( { - value: props.value - ? props.type === HTML5InputTypes.CHECKBOX - ? Array.isArray(props.value) - ? props.value - : undefined - : props.type === HTML5InputTypes.DATE - ? !isValidDate(parseDate(props.format as string, props.value as string)) - ? undefined - : props.value - : (props.value as KeyValue) - : undefined, + value, disabled: props.disabled, }, { diff --git a/src/lib/services/NgxTranslateService.ts b/src/lib/services/NgxTranslateService.ts new file mode 100644 index 00000000..7417bf01 --- /dev/null +++ b/src/lib/services/NgxTranslateService.ts @@ -0,0 +1,39 @@ +import { inject, Injectable } from '@angular/core'; +import { + InterpolatableTranslationObject, + InterpolationParameters, + TranslateService, + Translation, +} from '@ngx-translate/core'; +import { DecafTranslateService } from '@decaf-ts/ui-decorators'; +import { firstValueFrom, Observable } from 'rxjs'; +import { Primitives } from '@decaf-ts/decorator-validation'; + +@Injectable({ + providedIn: 'root', +}) +export class NgxTranslateService extends DecafTranslateService implements DecafTranslateService { + private translateService = inject(TranslateService); + + override instant(key: string, interpolateParams?: InterpolationParameters): Translation { + return this.translateService.instant(key, interpolateParams); + } + + override translate(key: string, params?: InterpolationParameters): Translation { + return this.instant(key, params); + } + + async get(key: string | string[], params?: InterpolationParameters | string): Promise { + if (key) { + if (typeof params === Primitives.STRING) { + params = { '0': params }; + } + return await firstValueFrom(this.translateService.get(key, (params || {}) as object)); + } + return key; + } + + setFallbackLang(lang: string): Observable { + return this.translateService.setFallbackLang(lang); + } +}