From b028b628695bba168e61fe010563aeaf5ec3ef0a Mon Sep 17 00:00:00 2001 From: Maxim Samsonov Date: Thu, 10 Sep 2026 00:23:38 +0300 Subject: [PATCH 1/4] chore: version bump to 0.15.3 --- api-node/package.json | 2 +- package-lock.json | 300 ++++++++++++++++---------------- package.json | 2 +- packages/contracts/package.json | 2 +- 4 files changed, 153 insertions(+), 153 deletions(-) diff --git a/api-node/package.json b/api-node/package.json index 5fe8d92..4ba20b2 100644 --- a/api-node/package.json +++ b/api-node/package.json @@ -1,6 +1,6 @@ { "name": "@klinok/api-node", - "version": "0.15.2", + "version": "0.15.3", "private": true, "type": "module", "main": "./dist/server.js", diff --git a/package-lock.json b/package-lock.json index ad16c16..2a73a00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "klinok", - "version": "0.15.2", + "version": "0.15.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "klinok", - "version": "0.15.2", + "version": "0.15.3", "workspaces": [ "api-node", "packages/contracts" @@ -39,7 +39,7 @@ }, "api-node": { "name": "@klinok/api-node", - "version": "0.15.2", + "version": "0.15.3", "dependencies": { "@fastify/cookie": "^11.0.2", "@fastify/rate-limit": "^11.1.0", @@ -1261,9 +1261,9 @@ "license": "MIT" }, "node_modules/@oxc-project/types": { - "version": "0.148.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.148.0.tgz", - "integrity": "sha512-Nm4s/jB+4FpFsPhWGEC4h7rzksesmtnMXomo6rCMcg/b8zLQuOziRgkCS1fxDCXOlJB/6Q8oABOZ/OP6RIPj9A==", + "version": "0.149.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.149.0.tgz", + "integrity": "sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA==", "dev": true, "license": "MIT", "funding": { @@ -1302,9 +1302,9 @@ } }, "node_modules/@rolldown/binding-android-arm-eabi": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.7.tgz", - "integrity": "sha512-EypzgnYCwyVY4NDHKzGmNJT5b+XaQEBniHxsMdeIQLB/tcCzZnhqrzHpZFbX9iaxx+5RiB8caATBtfvZP7zVxQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.8.tgz", + "integrity": "sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw==", "cpu": [ "arm" ], @@ -1319,9 +1319,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.7.tgz", - "integrity": "sha512-l17HE9EweWaqJZhuUuNBN/FzM62xw+DECVnJyvMsxn8vJFAGLy5QfLDoYAcronkAN8VxKZHezDpulHDPx95vFw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.8.tgz", + "integrity": "sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ==", "cpu": [ "arm64" ], @@ -1336,9 +1336,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.7.tgz", - "integrity": "sha512-8ED8ELFvHXc6OCETIn4gXObPiaR6bckM/ipXtbzlPVDRMBfEGjCKgO90F9YtfdpDatVx/ZQw7aZ1vUMf/+T3Mw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.8.tgz", + "integrity": "sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA==", "cpu": [ "arm64" ], @@ -1353,9 +1353,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.7.tgz", - "integrity": "sha512-/WPripjtiAIZ2tWY7ddijORT0Ujg87wxWW/qcoFVCKAWVDPhtY0xr7Dj0M3GyNGz60jGwTElhro/mkF9dT7dDQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.8.tgz", + "integrity": "sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA==", "cpu": [ "x64" ], @@ -1370,9 +1370,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.7.tgz", - "integrity": "sha512-14DI4NcqpvbICxSnGLx3PmtDaWqRP/KGSGb6C+JLLVPeZRl6dKdHba3pGsqT3vpdTqhEYIPG0MMQ8c0xYqoJxA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.8.tgz", + "integrity": "sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ==", "cpu": [ "x64" ], @@ -1387,9 +1387,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.7.tgz", - "integrity": "sha512-bxrWIRvHWQvbJwi+VIie/kDJmQxcNE6xxWwZdqF/ExVAigtHkv54WTLQPb+QsZdnFy18fg7JPfWGL0RH6vwIlQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.8.tgz", + "integrity": "sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q==", "cpu": [ "arm" ], @@ -1404,9 +1404,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.7.tgz", - "integrity": "sha512-toOY2BChBZyuxU7OYX6Tn389di4IzAqPTycVcci0O7FSfBqzRB3RZn+K5Is6ANf4tmgRd/K1yZTsNTXbkXsnLg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.8.tgz", + "integrity": "sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew==", "cpu": [ "arm64" ], @@ -1424,9 +1424,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.7.tgz", - "integrity": "sha512-lAIXTH/aiLRLxsTgQvfhjo4K1ydWIp00+V0voOr9beb/9ZmkUFrSIb03dXNFRgMNvkE6oGsF10ioQ6UsI+vS5Q==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.8.tgz", + "integrity": "sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA==", "cpu": [ "arm64" ], @@ -1444,9 +1444,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.7.tgz", - "integrity": "sha512-kdnwS28Pkenp/mZMRwjXXXwxQ7pIsm+bF919LUK93BOyhcLsrVKdP2p9fxpiPNPAbNuch8ypQt0pm2P2LYCAGg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.8.tgz", + "integrity": "sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA==", "cpu": [ "ppc64" ], @@ -1464,9 +1464,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.7.tgz", - "integrity": "sha512-516OdsyLdr5E65paF3yBF55t8mfm9+gmtCsK3xI7XKXIT7EfRlHhxL8K/NR6Hu8BWSgF5+1w74lTL0+nxcc8Qw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.8.tgz", + "integrity": "sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ==", "cpu": [ "s390x" ], @@ -1484,9 +1484,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.7.tgz", - "integrity": "sha512-r8/z8n7GFaYRln3xmP1Cxy0HH/HLM0uBUPkEuSVEfKGDA89M0FsZRZJRSwe/tJjRx+fpH/gjorfhB8tmEbSFLA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.8.tgz", + "integrity": "sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g==", "cpu": [ "x64" ], @@ -1504,9 +1504,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.7.tgz", - "integrity": "sha512-pAsE8iiDxUg1xBqdhrTfg45AVDVpirjz00sblEYClGNNcMnDb+e8beQgqIAw6LvauX/APvgxUnwrgun/YYGBhw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.8.tgz", + "integrity": "sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA==", "cpu": [ "x64" ], @@ -1524,9 +1524,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.7.tgz", - "integrity": "sha512-lTcIYmmnQQA8Or/2DatS6oSqcdLHvendjS+zLu+FwgToynWMRSmQdpM65fTANJgIS4mjbMOo5KT2lnT9SAb96w==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.8.tgz", + "integrity": "sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg==", "cpu": [ "arm64" ], @@ -1541,9 +1541,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.7.tgz", - "integrity": "sha512-e3Gu3WxbNk/UqQhxqU7YIYO+9ZBvWNz3U+h/qRFosscMFzdRPbXYSaSWgSnklv2fz1TgzBTcti2z35c/7irsHw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.8.tgz", + "integrity": "sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A==", "cpu": [ "arm64" ], @@ -1558,9 +1558,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.7.tgz", - "integrity": "sha512-W/jg5qoRSqjsEv0+dZi4e687mcHqmVuU0P4fK6qS/xjetW2Gmc1W8j//z5nAeNcC8Ttm0hV46IjcYeuVwYhuiw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.8.tgz", + "integrity": "sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng==", "cpu": [ "x64" ], @@ -1628,9 +1628,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", - "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", + "version": "24.13.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.4.tgz", + "integrity": "sha512-YJ7EqCstVTzIr0fMr7qul/977en+pQHrfmuKIo6Zr9i75Be21dr3MovcfvGtyvi2HAUrRerWps5sMO9I7WaxDw==", "dev": true, "license": "MIT", "dependencies": { @@ -1660,17 +1660,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.69.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.69.0.tgz", - "integrity": "sha512-t5jQTKPIgVW1PE6dR6H6Qz5gm8zjMlX5/2gRaOGd9eO6V7J+tQc6iWKukEe7dY8u9HyYasQ0yfF0/FSSTEO2gA==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.70.0.tgz", + "integrity": "sha512-/v8HZt6RlyIZxB3ntehELOcUcfxKPVGWXnQdJuHRmzrqgF8nQypcC/oxGW+Ot4VGKDq81XugPKxx0n5PBtf9PA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.69.0", - "@typescript-eslint/type-utils": "8.69.0", - "@typescript-eslint/utils": "8.69.0", - "@typescript-eslint/visitor-keys": "8.69.0", + "@typescript-eslint/scope-manager": "8.70.0", + "@typescript-eslint/type-utils": "8.70.0", + "@typescript-eslint/utils": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -1683,22 +1683,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.69.0", + "@typescript-eslint/parser": "^8.70.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.69.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.69.0.tgz", - "integrity": "sha512-l4b0DhWioGg6Gt2ebGlvfkFMOjRsauxtsnDRwUSRX1qHq3HdTfQHV8wW9zEXeciai6HfeaKOedQn2Zoofx3WBw==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.70.0.tgz", + "integrity": "sha512-zYvrmj9Yxd63UGaXw+kdt6A0F0s0qveJyuatIM77bYC2DE4pgmg7a50u8LR7PRtXd0x+h+Tl3eXabGm06SWd3Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.69.0", - "@typescript-eslint/types": "8.69.0", - "@typescript-eslint/typescript-estree": "8.69.0", - "@typescript-eslint/visitor-keys": "8.69.0", + "@typescript-eslint/scope-manager": "8.70.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0", "debug": "^4.4.3" }, "engines": { @@ -1714,14 +1714,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.69.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.69.0.tgz", - "integrity": "sha512-yi4obFrHMmnsesWehHbkg9zMA7Jt8cXT+mKM08G999pH1yT6nqgsHx7MYm0uY1wAj8CqiBXYRJ7WAT0QdQHQXg==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.70.0.tgz", + "integrity": "sha512-hFHbTNqhU9G+2eKFXCBVb1tjFT/LceiJ4+HfLO4pTpDI0KHi6iajpcFFkaSQ9gXmCh7n82A0PthaayEdN6mspQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.69.0", - "@typescript-eslint/types": "^8.69.0", + "@typescript-eslint/tsconfig-utils": "^8.70.0", + "@typescript-eslint/types": "^8.70.0", "debug": "^4.4.3" }, "engines": { @@ -1736,14 +1736,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.69.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.69.0.tgz", - "integrity": "sha512-ewfspqWvSxKSOaplqAUNbaSFO0eB6w1EtQ+esfYFRm3614Ty4uNtExkcbgd6nWsXphbqKyf9ZYdbZdv2xEoWEQ==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.70.0.tgz", + "integrity": "sha512-8nP3Kwh5hlgZ4FicGvmznAmJe8UL4sdU8tLukrPaMuQmDuk4Y8xYfzu/aYZW4xT2JCgc7H/TpDI5cGlxcWJSqQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.69.0", - "@typescript-eslint/visitor-keys": "8.69.0" + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1754,9 +1754,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.69.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.69.0.tgz", - "integrity": "sha512-xNqK7YTDZsLniQMV/4rpFR8Z5JlqeRvVjuG1YgF/mdPVH84HSD19L8CczMA0qg2RfwEV231GHH3VnToJDo4MfQ==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.0.tgz", + "integrity": "sha512-adnkeeNq9Sq1sUf4+FRVc0KdgYghzsgFpZSQVZVvY0LCuUuN0FnQgyGzCJeC4fW1cdXseBAjU2EOqUIjbNcZUw==", "dev": true, "license": "MIT", "engines": { @@ -1771,15 +1771,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.69.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.69.0.tgz", - "integrity": "sha512-ZfoJAVg3JZndQEpEl9petVlxau3lRuElc4HRMuAlLCf8to04/iHz692RUSNmXKDjEuJmIL+KZ2/BsOcBc16dsA==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.70.0.tgz", + "integrity": "sha512-NUMKIhYVaVIVLnRL9CRt+VVcuLgSHUCpXn4/+K8wql+vdInUzvx8BjUO1oJ7cG9shjFJKtF8F8Hh2kCh3/KBVw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.69.0", - "@typescript-eslint/typescript-estree": "8.69.0", - "@typescript-eslint/utils": "8.69.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0", + "@typescript-eslint/utils": "8.70.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -1796,9 +1796,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.69.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.69.0.tgz", - "integrity": "sha512-K3VrubUPhlo9VDBS6QdI8YB5j7ClpqLRdefcz6PFrhnwicehBweqQ9Evhl4l+FYz0HdDmMqIiSX0aldGRYtDCA==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.70.0.tgz", + "integrity": "sha512-asTOIYhDg4zdzOScCyaytrsV3cR6B4ecPQlXw/dJIm7J/MZTtCtfVII9JD8Geh4jTCrK/Xe6cg5UevoleMcoJQ==", "dev": true, "license": "MIT", "engines": { @@ -1810,16 +1810,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.69.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.69.0.tgz", - "integrity": "sha512-AdFkgqck3Vudb/kWnxlyafU/4aBhHrbQ9locP2N4psXTy5mOBg0SHJumnLvx7r6g1gV4DKvUFwV2nJZBoqOD8w==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.0.tgz", + "integrity": "sha512-d9NmHMPEKQ7QCLLm1jI3zmoQBwT5KwFYjXBJ9ymZfKCUU+5rmTRykKAFvH5Qn/ZCds3CEAFS9OC9M/jkl0X2bA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.69.0", - "@typescript-eslint/tsconfig-utils": "8.69.0", - "@typescript-eslint/types": "8.69.0", - "@typescript-eslint/visitor-keys": "8.69.0", + "@typescript-eslint/project-service": "8.70.0", + "@typescript-eslint/tsconfig-utils": "8.70.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -1838,16 +1838,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.69.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.69.0.tgz", - "integrity": "sha512-tUbx60BBqQa31kXF5MCsOOLL5E/WzUuxIn7YpAvq+eaUlqvk8/NXnXMBNAdLCr0icjkzem7iUA5QqWHe/hJ1aw==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.70.0.tgz", + "integrity": "sha512-oZmtKJz/4fufZ2p3+Cn3ijEojcdfR+1zYDH2xKYrEly0dR/Q/1xUPRCOlKGxod78nWlU2UnDe09GZ3TaknBFGA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.69.0", - "@typescript-eslint/types": "8.69.0", - "@typescript-eslint/typescript-estree": "8.69.0" + "@typescript-eslint/scope-manager": "8.70.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1862,13 +1862,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.69.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.69.0.tgz", - "integrity": "sha512-+rmdgPA+EXkNgKYvHvFfhrs35utXbwaC5PGpDquSXcoXQDKUA5UjV0LmTucG/4JXkM31BTu4TilHtrN8IVBe8w==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.70.0.tgz", + "integrity": "sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.69.0", + "@typescript-eslint/types": "8.70.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -2412,9 +2412,9 @@ } }, "node_modules/ast-v8-to-istanbul": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.5.tgz", - "integrity": "sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.6.tgz", + "integrity": "sha512-fvpl29helSO2w/z7utIbrkNXILdrLwDwAMH2I/zPKlGf5244+gf+B4cyS1sANcrPY2h+hWCGSgC8N61s/+AF9A==", "dev": true, "license": "MIT", "dependencies": { @@ -2473,9 +2473,9 @@ } }, "node_modules/bidi-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", - "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.1.0.tgz", + "integrity": "sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==", "dev": true, "license": "MIT", "dependencies": { @@ -3445,9 +3445,9 @@ } }, "node_modules/ignore": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.8.tgz", - "integrity": "sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.9.tgz", + "integrity": "sha512-brTTsvFRt5C1gGHtPst/281UjPD5t9fBqbgoMPlVWy11ZLTPfu7HxK4ZYqO9H7o/yC9rSTCI85EaQ4OoY12qYw==", "dev": true, "license": "MIT", "engines": { @@ -4221,9 +4221,9 @@ } }, "node_modules/obug": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", - "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.2.1.tgz", + "integrity": "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", @@ -4307,9 +4307,9 @@ } }, "node_modules/parse5/node_modules/entities": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", - "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz", + "integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -4769,13 +4769,13 @@ "license": "MIT" }, "node_modules/rolldown": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.7.tgz", - "integrity": "sha512-g0EtLvBjTUB7jhyV0S/TCup3v/XSVl45vUIGbOGU4QPiyjTenCe4mKuFvW9fEgYmS2Fo42AUssRmNuMziXdrig==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.8.tgz", + "integrity": "sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.148.0", + "@oxc-project/types": "=0.149.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -4785,21 +4785,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm-eabi": "1.2.7", - "@rolldown/binding-android-arm64": "1.2.7", - "@rolldown/binding-darwin-arm64": "1.2.7", - "@rolldown/binding-darwin-x64": "1.2.7", - "@rolldown/binding-freebsd-x64": "1.2.7", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.7", - "@rolldown/binding-linux-arm64-gnu": "1.2.7", - "@rolldown/binding-linux-arm64-musl": "1.2.7", - "@rolldown/binding-linux-ppc64-gnu": "1.2.7", - "@rolldown/binding-linux-s390x-gnu": "1.2.7", - "@rolldown/binding-linux-x64-gnu": "1.2.7", - "@rolldown/binding-linux-x64-musl": "1.2.7", - "@rolldown/binding-openharmony-arm64": "1.2.7", - "@rolldown/binding-win32-arm64-msvc": "1.2.7", - "@rolldown/binding-win32-x64-msvc": "1.2.7" + "@rolldown/binding-android-arm-eabi": "1.2.8", + "@rolldown/binding-android-arm64": "1.2.8", + "@rolldown/binding-darwin-arm64": "1.2.8", + "@rolldown/binding-darwin-x64": "1.2.8", + "@rolldown/binding-freebsd-x64": "1.2.8", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.8", + "@rolldown/binding-linux-arm64-gnu": "1.2.8", + "@rolldown/binding-linux-arm64-musl": "1.2.8", + "@rolldown/binding-linux-ppc64-gnu": "1.2.8", + "@rolldown/binding-linux-s390x-gnu": "1.2.8", + "@rolldown/binding-linux-x64-gnu": "1.2.8", + "@rolldown/binding-linux-x64-musl": "1.2.8", + "@rolldown/binding-openharmony-arm64": "1.2.8", + "@rolldown/binding-win32-arm64-msvc": "1.2.8", + "@rolldown/binding-win32-x64-msvc": "1.2.8" } }, "node_modules/safe-regex2": { @@ -5032,22 +5032,22 @@ } }, "node_modules/tldts": { - "version": "7.4.11", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.11.tgz", - "integrity": "sha512-aBiNayCfTQxuIJBm06M+xR14cYaYlDlSXZbgsnKzKNxDKUVq7KFwTjwBSsb7m9Y5xO8WfPnBc63WaYFMTGlvqw==", + "version": "7.4.12", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.12.tgz", + "integrity": "sha512-WylhSDKVeYnWXL3a+vKTaOxjnOeEGw938hImY8zoRWJjRRK/Jp1K+IihBzIONpUmW4e3WmXT6q5FW6vlESVZCA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.4.11" + "tldts-core": "^7.4.12" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.4.11", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.11.tgz", - "integrity": "sha512-CW3WN2rIIE/Of21mulhgnGOwoDyEFNygyIBOONSdyAuSATgMMUCpLeUlB+E8sAwA5xRV9hYPl+kyZ9citHCaKg==", + "version": "7.4.12", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.12.tgz", + "integrity": "sha512-nYNzS2WRf4QJmjzFFgAxLOBjyBxAGRbCy9PVBPaglcYyYajh40VBn+v5Ngr96ZMc7oM0+aCJdtQnNejvdBnXMQ==", "dev": true, "license": "MIT" }, @@ -5588,7 +5588,7 @@ }, "packages/contracts": { "name": "@klinok/contracts", - "version": "0.15.2" + "version": "0.15.3" } } } diff --git a/package.json b/package.json index 070b185..1ce55bf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "klinok", "private": true, - "version": "0.15.2", + "version": "0.15.3", "type": "module", "workspaces": [ "api-node", diff --git a/packages/contracts/package.json b/packages/contracts/package.json index c4a51e3..d6b7890 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -1,6 +1,6 @@ { "name": "@klinok/contracts", - "version": "0.15.2", + "version": "0.15.3", "private": true, "type": "module", "main": "./dist/index.js", From c7d88f73e79475f6ddc7a3edd0905172b5ba6287 Mon Sep 17 00:00:00 2001 From: Maxim Samsonov Date: Thu, 10 Sep 2026 00:38:05 +0300 Subject: [PATCH 2/4] fix: preserve newline characters (#122) --- src/components/MedicalRecordEntry.vue | 2 +- src/components/TherapeuticAppointmentView.vue | 14 +++---- src/styles.css | 2 +- tests/medicalRecordEntry.spec.ts | 41 ++++++++++++++++++- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/components/MedicalRecordEntry.vue b/src/components/MedicalRecordEntry.vue index 9df0206..f98d9f0 100644 --- a/src/components/MedicalRecordEntry.vue +++ b/src/components/MedicalRecordEntry.vue @@ -284,7 +284,7 @@ function emitToggle(event: Event) {
{{ detail.value }}
-

{{ freeText(item.section.value) }}

+

{{ freeText(item.section.value) }}

-
Комментарий
{{ value.diseaseAnamnesis.text }}
+
Комментарий
{{ value.diseaseAnamnesis.text }}
-

{{ value.recommendations }}

-

{{ value.prescriptions }}

+

{{ value.recommendations }}

+

{{ value.prescriptions }}

Перенесённые данные

diff --git a/src/styles.css b/src/styles.css index 97ee777..cd1273a 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1276,7 +1276,7 @@ label > input[type="checkbox"] { @container (max-width: 760px) { .therapeutic-problem-fields { grid-template-columns: minmax(0, 1fr); } } -.therapeutic-history-text { white-space: pre-wrap; overflow-wrap: anywhere; } +.medical-history-text { white-space: pre-wrap; overflow-wrap: anywhere; } .therapeutic-appointment-view { display: grid; gap: 14px; } .therapeutic-history-block { display: grid; min-width: 0; gap: 7px; } .therapeutic-history-problems { display: grid; gap: 7px; } diff --git a/tests/medicalRecordEntry.spec.ts b/tests/medicalRecordEntry.spec.ts index 556bd54..0d23614 100644 --- a/tests/medicalRecordEntry.spec.ts +++ b/tests/medicalRecordEntry.spec.ts @@ -573,6 +573,45 @@ describe("MedicalRecordEntry", () => { expect(wrapper.emitted("delete")?.[0]).toEqual([wrapper.props("record")]); }); + it("preserves line breaks in standalone recommendations and procedures", () => { + const wrapper = mount(MedicalRecordEntry, { + props: { + record: { + ...record, + sections: { + "what-happened": record.sections["what-happened"], + procedures: { + kind: "procedures", + templateVersion: "free-text-v0", + value: { text: "Первая манипуляция\nВторая манипуляция" }, + authorAccountId: "doctor-1", + authorDisplayName: "Вера Врач", + updatedAt: "2026-07-21T11:00:00.000Z", + }, + recommendations: { + kind: "recommendations", + templateVersion: "free-text-v0", + value: { text: "Первая рекомендация\nВторая рекомендация" }, + authorAccountId: "doctor-1", + authorDisplayName: "Вера Врач", + updatedAt: "2026-07-21T11:30:00.000Z", + }, + outcome: record.sections.outcome, + }, + }, + mode: "details", + confirmed: true, + open: true, + }, + }); + + const sectionText = (heading: string) => wrapper.findAll(".encounter-history-section") + .find((section) => section.get("h3").text() === heading)! + .get(".medical-history-text").text(); + expect(sectionText("Манипуляции")).toBe("Первая манипуляция\nВторая манипуляция"); + expect(sectionText("Рекомендации")).toBe("Первая рекомендация\nВторая рекомендация"); + }); + it("renders diagnosis v2 without an absent confirmed diagnosis", () => { const diagnosis = record.sections.diagnosis!; const wrapper = mount(MedicalRecordEntry, { @@ -839,7 +878,7 @@ describe("MedicalRecordEntry", () => { expect(gingivitis.get(":scope > span").text()).toBe("Гингивит/гингивостоматит: Наблюдается"); expect(gingivitisGrade.get(":scope > span").text()).toBe("Незначительный"); expect(gingivitisGrade.element.parentElement?.parentElement).toBe(gingivitis.element); - expect(section.get(".therapeutic-history-text").text()).toBe("Снижение аппетита\nсо вчерашнего дня"); + expect(section.get(".medical-history-text").text()).toBe("Снижение аппетита\nсо вчерашнего дня"); }); it("omits empty therapeutic history blocks", () => { From 1f9e029edafe8336f70bdcfb7126cb5fbc8a820d Mon Sep 17 00:00:00 2001 From: Maxim Samsonov Date: Thu, 10 Sep 2026 13:53:30 +0300 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86?= =?UTF-8?q?=D0=B0=20=D1=81=D1=80=D0=B0=D0=B2=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B5=20?= =?UTF-8?q?=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=BE=D0=B3=D0=BE=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BB=D0=B8=D1=87=D0=B5=D1=81=D1=82=D0=B2=D0=B0=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BA=D0=B0=D0=B7=D0=B0=D1=82=D0=B5=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/operational.spec.ts | 66 ++++++++++++++++++++++--- src/components/LaboratoryComparison.vue | 11 ++++- src/styles.css | 21 +++++++- tests/laboratoryComparison.spec.ts | 13 ++++- 4 files changed, 101 insertions(+), 10 deletions(-) diff --git a/e2e/operational.spec.ts b/e2e/operational.spec.ts index 7142a2e..0e741ab 100644 --- a/e2e/operational.spec.ts +++ b/e2e/operational.spec.ts @@ -642,6 +642,12 @@ test("fresh provisioning, Doctor approval, grant, draft, and confirmation", asyn await hematocritInput.fill("42"); const hemoglobinInput = await addLaboratoryIndicator(/Гемоглобин \(Hgb\)/, "Гемоглобин (Hgb)"); await hemoglobinInput.fill("145"); + const erythrocytesInput = await addLaboratoryIndicator(/Эритроциты \(RBC\)/, "Эритроциты (RBC)"); + await erythrocytesInput.fill("7.2"); + const plateletsInput = await addLaboratoryIndicator(/Тромбоциты \(Plt\)/, "Тромбоциты (Plt)"); + await plateletsInput.fill("256"); + const meanCellVolumeInput = await addLaboratoryIndicator(/Средний объем эритроцита \(MCV\)/, "Средний объем эритроцита (MCV)"); + await meanCellVolumeInput.fill("45"); expect(await laboratoryCard.locator(".laboratory-study-card").evaluate((card) => { const results = card.querySelector(".laboratory-panel-results"); const create = card.querySelector(".laboratory-indicator-create"); @@ -1596,18 +1602,60 @@ test("fresh provisioning, Doctor approval, grant, draft, and confirmation", asyn ".owner-pet-detail > :is(.owner-epicrisis, .laboratory-comparison, .owner-medical-record)", )); await ownerPage.setViewportSize({ width: 1280, height: 720 }); - await laboratoryComparison.locator(".app-catalog-toggle").click(); - await laboratoryComparison.getByRole("option", { name: /Лейкоциты \(WBC\)/ }).click(); - await laboratoryComparison.locator(".app-catalog-toggle").click(); - await laboratoryComparison.getByRole("option", { name: /Гематокрит \(Hct, PCV\)/ }).click(); + const laboratoryIndicatorToggle = laboratoryComparison.locator(".app-catalog-toggle"); + for (const indicatorName of [ + /Лейкоциты \(WBC\)/, + /Гематокрит \(Hct, PCV\)/, + /Гемоглобин \(Hgb\)/, + /Эритроциты \(RBC\)/, + /Тромбоциты \(Plt\)/, + /Средний объем эритроцита \(MCV\)/, + ]) { + await laboratoryIndicatorToggle.click(); + await laboratoryComparison.getByRole("option", { name: indicatorName }).click(); + } await expect(laboratoryComparison.locator( ".laboratory-results thead .laboratory-comparison-column-heading", - )).toHaveCount(2); + )).toHaveCount(6); await expect(laboratoryComparison.locator(".laboratory-comparison-selections")).toHaveCount(0); await expect(laboratoryComparison.locator(".laboratory-comparison-table")).toBeVisible(); await expect(laboratoryComparison.locator(".laboratory-results-scroll")).toHaveClass(/owner-access-table-wrap/); await expect(laboratoryComparison.locator(".laboratory-results")).toHaveClass(/owner-access-table/); await expect(laboratoryComparison.locator(".laboratory-results")).toBeVisible(); + await ownerPage.setViewportSize({ width: 900, height: 720 }); + const laboratoryResultsScroll = laboratoryComparison.locator(".laboratory-results-scroll"); + const laboratoryLayout = await laboratoryResultsScroll.evaluate((scroll) => { + const table = scroll.querySelector(".laboratory-results")!; + const headings = [...table.querySelectorAll("thead th")]; + const panel = scroll.closest(".laboratory-comparison")!; + return { + scrollable: scroll.scrollWidth > scroll.clientWidth + 1, + panelFits: panel.scrollWidth <= panel.clientWidth + 1, + pageFits: document.documentElement.scrollWidth <= window.innerWidth + 1, + tableWidth: table.getBoundingClientRect().width, + dateWidth: headings[0]!.getBoundingClientRect().width, + studyWidth: headings[1]!.getBoundingClientRect().width, + indicatorWidths: headings.slice(2).map((heading) => heading.getBoundingClientRect().width), + dateWhiteSpace: getComputedStyle(headings[0]!).whiteSpace, + indicatorOverflowWrap: getComputedStyle(headings[2]!.querySelector(".laboratory-comparison-column-label")!).overflowWrap, + }; + }); + expect(laboratoryLayout).toMatchObject({ + scrollable: true, + panelFits: true, + pageFits: true, + dateWhiteSpace: "nowrap", + indicatorOverflowWrap: "normal", + }); + expect(laboratoryLayout.dateWidth).toBeGreaterThanOrEqual(118); + expect(laboratoryLayout.studyWidth).toBeGreaterThanOrEqual(222); + expect(Math.min(...laboratoryLayout.indicatorWidths)).toBeGreaterThanOrEqual(166); + expect(await laboratoryResultsScroll.evaluate((scroll) => { + scroll.scrollLeft = scroll.scrollWidth; + const offset = scroll.scrollLeft; + scroll.scrollLeft = 0; + return offset; + })).toBeGreaterThan(0); const laboratoryDateHeader = laboratoryComparison.locator(".laboratory-results th").first(); await expect(laboratoryDateHeader).toHaveAttribute("aria-sort", "descending"); await expectTopAligned( @@ -1620,7 +1668,7 @@ test("fresh provisioning, Doctor approval, grant, draft, and confirmation", asyn await expect(laboratoryComparison).toBeVisible({ timeout: replicationTimeout }); await expect(laboratoryComparison.locator( ".laboratory-results thead .laboratory-comparison-column-heading", - )).toHaveCount(2); + )).toHaveCount(6); const removeLeukocytes = laboratoryComparison.getByRole("button", { name: /Удалить показатель «Лейкоциты \(WBC\),/ }); const removeHematocrit = laboratoryComparison.getByRole("button", { name: /Удалить показатель «Гематокрит \(Hct, PCV\), %»/ }); await expect(removeLeukocytes).toBeVisible(); @@ -1639,6 +1687,12 @@ test("fresh provisioning, Doctor approval, grant, draft, and confirmation", asyn expect(Math.abs(removeControlMetrics.iconWidth - removeControlMetrics.fontSize)).toBeLessThanOrEqual(1); await removeLeukocytes.click(); await expect(removeLeukocytes).toHaveCount(0); + await expect(laboratoryComparison.locator( + ".laboratory-results thead .laboratory-comparison-column-heading", + )).toHaveCount(5); + expect(await laboratoryComparison.locator(".laboratory-results").evaluate((table) => + table.getBoundingClientRect().width + )).toBeLessThan(laboratoryLayout.tableWidth); await expect(removeHematocrit).toBeVisible(); await expect(laboratoryComparison.getByRole("columnheader", { name: /Лейкоциты \(WBC\)/ })).toHaveCount(0); await expect(laboratoryComparison.getByRole("columnheader", { name: /Гематокрит \(Hct, PCV\)/ })).toBeVisible(); diff --git a/src/components/LaboratoryComparison.vue b/src/components/LaboratoryComparison.vue index 33c11f1..ccc3bb2 100644 --- a/src/components/LaboratoryComparison.vue +++ b/src/components/LaboratoryComparison.vue @@ -53,6 +53,7 @@ const selectedIndicators = computed(() => selectedIds.value.flatMap((id) => { const indicator = indicatorMap.value.get(id); return indicator ? [indicator] : []; })); +const indicatorColumnsWidth = computed(() => `${selectedIds.value.length * 10.5}rem`); const rows = computed(() => occurrences.value .filter(({ study }) => study.mode === "panel" && study.results.some((result) => selectedIds.value.includes(result.indicatorId))) .sort((left, right) => { @@ -131,7 +132,15 @@ function removeIndicator(id: string) { @update:direction="updateDateSort" />
- +
+ + + + +
diff --git a/src/styles.css b/src/styles.css index cd1273a..32db1df 100644 --- a/src/styles.css +++ b/src/styles.css @@ -3492,8 +3492,18 @@ label > input[type="checkbox"] { box-shadow: 0 0 0 1px var(--danger); } .laboratory-metadata { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: .75rem; align-items: start; } -.laboratory-results-scroll { max-width: 100%; } -.laboratory-results { min-width: 42rem; } +.laboratory-results-scroll { + max-width: 100%; + overscroll-behavior-x: contain; + scrollbar-width: thin; +} +.laboratory-results { + --laboratory-indicator-columns-width: 0rem; + min-width: max(42rem, calc(21.5rem + var(--laboratory-indicator-columns-width))); +} +.laboratory-results-date-column { width: 7.5rem; } +.laboratory-results-study-column { width: 14rem; } +.laboratory-results-indicator-column { width: 10.5rem; } .laboratory-result-content { display: grid; min-width: 0; gap: 2px; } .laboratory-result-reference { color: var(--text-muted); } .laboratory-comparison.panel { @@ -3534,6 +3544,13 @@ label > input[type="checkbox"] { .laboratory-results .table-sort-button { min-height: 0; align-items: flex-start; } .laboratory-results-mobile-columns { display: none; } .laboratory-comparison-table { display: grid; min-width: 0; gap: 12px; } +@media (min-width: 761px) { + .laboratory-results :is(th, td):first-child { white-space: nowrap; } + .laboratory-results .laboratory-comparison-column-label { + overflow-wrap: normal; + word-break: normal; + } +} .laboratory-panel-results { container-type: inline-size; width: 100%; diff --git a/tests/laboratoryComparison.spec.ts b/tests/laboratoryComparison.spec.ts index dac47ba..234247a 100644 --- a/tests/laboratoryComparison.spec.ts +++ b/tests/laboratoryComparison.spec.ts @@ -129,7 +129,15 @@ describe("LaboratoryComparison", () => { expect(comparison.text()).toContain("Реф.: 120–180"); expect(comparison.findAll("tbody td").filter((cell) => cell.text() === "—")).toHaveLength(2); expect(comparison.get(".laboratory-results-scroll").classes()).toContain("owner-access-table-wrap"); - expect(comparison.get(".laboratory-results").classes()).toContain("owner-access-table"); + const resultsTable = comparison.get(".laboratory-results"); + expect(resultsTable.classes()).toContain("owner-access-table"); + expect(resultsTable.attributes("style")).toContain("--laboratory-indicator-columns-width: 21rem"); + expect(resultsTable.findAll("col").map((column) => column.classes())).toEqual([ + ["laboratory-results-date-column"], + ["laboratory-results-study-column"], + ["laboratory-results-indicator-column"], + ["laboratory-results-indicator-column"], + ]); expect(comparison.findAll(".laboratory-results th").map((header) => header.text())).toEqual([ "Дата", "Исследование", @@ -274,6 +282,9 @@ describe("LaboratoryComparison", () => { await removeHematocrit.trigger("click"); expect(restored.findAll(".laboratory-results thead .laboratory-comparison-column-heading")).toHaveLength(1); + expect(restored.get(".laboratory-results").attributes("style")) + .toContain("--laboratory-indicator-columns-width: 10.5rem"); + expect(restored.findAll(".laboratory-results-indicator-column")).toHaveLength(1); expect(restored.findAll(".laboratory-results th").map((header) => header.text())).not.toContain("Гематокрит, %"); expect(restored.get(".laboratory-results").text()).toContain("Гемоглобин, г/л"); expect(JSON.parse(localStorage.getItem(key) ?? "null").indicatorIds).toEqual([hemoglobin.indicatorId]); From bf23c57bbcbfb843b2955f994bdfe413dfe8faa6 Mon Sep 17 00:00:00 2001 From: Maxim Samsonov Date: Thu, 10 Sep 2026 14:44:06 +0300 Subject: [PATCH 4/4] fix: auto close of laboratory values selector (#120) --- e2e/operational.spec.ts | 13 ++++++ src/components/AppCatalogCombobox.vue | 37 +++++++++++++--- tests/appCatalogCombobox.spec.ts | 64 +++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 5 deletions(-) diff --git a/e2e/operational.spec.ts b/e2e/operational.spec.ts index 0e741ab..e2c5c62 100644 --- a/e2e/operational.spec.ts +++ b/e2e/operational.spec.ts @@ -1603,6 +1603,19 @@ test("fresh provisioning, Doctor approval, grant, draft, and confirmation", asyn )); await ownerPage.setViewportSize({ width: 1280, height: 720 }); const laboratoryIndicatorToggle = laboratoryComparison.locator(".app-catalog-toggle"); + await laboratoryIndicatorToggle.click(); + await ownerPage.mouse.move(0, 0); + const ownerStateRefresh = ownerPage.waitForResponse((response) => { + const url = new URL(response.url()); + return response.request().method() === "GET" + && url.pathname.endsWith("/api/state") + && url.searchParams.get("role") === "owner" + && (response.ok() || response.status() === 304); + }); + await laboratoryIndicatorToggle.hover(); + await ownerStateRefresh; + await expect(laboratoryIndicatorToggle).toHaveAttribute("aria-expanded", "true"); + await laboratoryIndicatorToggle.click(); for (const indicatorName of [ /Лейкоциты \(WBC\)/, /Гематокрит \(Hct, PCV\)/, diff --git a/src/components/AppCatalogCombobox.vue b/src/components/AppCatalogCombobox.vue index 7df858f..63922d6 100644 --- a/src/components/AppCatalogCombobox.vue +++ b/src/components/AppCatalogCombobox.vue @@ -152,7 +152,11 @@ const activeOptionId = computed(() => showingCategories.value ? `${listboxId}-${optionIndex(filteredOptions.value[activeCategoryIndex.value]!.id)}` : `${listboxId}-category-${activeCategoryIndex.value - filteredOptions.value.length}` : activeIndex.value >= 0 ? `${listboxId}-${activeIndex.value}` : undefined); -const rootItemCount = computed(() => filteredOptions.value.length + categories.value.length); +const rootItemKeys = computed(() => [ + ...filteredOptions.value.map((option) => `option:${option.id}`), + ...categories.value.map((category) => `category:${category.id}`), +]); +const rootItemCount = computed(() => rootItemKeys.value.length); const toggleTitle = computed(() => { if (!allOptions.value.length) return props.disabledTitle; return open.value ? props.hideOptionsTitle : props.showOptionsTitle; @@ -323,15 +327,38 @@ function handleDocumentInteraction(event: Event) { if (open.value && !root.value?.contains(event.target as Node)) closeOptions(); } +function reconcileActiveIndex( + options: readonly string[], + previousOptions: readonly string[], + currentIndex: number, +): number { + if (!options.length) return -1; + const activeId = previousOptions[currentIndex]; + const nextIndex = activeId === undefined ? -1 : options.indexOf(activeId); + return nextIndex >= 0 ? nextIndex : Math.min(Math.max(currentIndex, 0), options.length - 1); +} + watch(() => [props.multiple, selectedLabel.value, customText.value, selectedIds.value.join("\u0000")], () => { if (!open.value) syncInputValue(); }, { immediate: true }); -watch(allOptions, () => { - closeOptions(); +watch(allOptions, (options) => { + if (!options.length) { + closeOptions(); + return; + } + if (open.value && activeCategoryId.value && !activeCategory.value) showCategories(); }); -watch(visibleOptions, (options) => { +watch(visibleOptions, (options, previousOptions) => { if (!open.value || showingCategories.value) return; - activeIndex.value = options.length ? Math.min(Math.max(activeIndex.value, 0), options.length - 1) : -1; + activeIndex.value = reconcileActiveIndex( + options.map((option) => option.id), + previousOptions.map((option) => option.id), + activeIndex.value, + ); +}); +watch(rootItemKeys, (items, previousItems) => { + if (!open.value || !showingCategories.value) return; + activeCategoryIndex.value = reconcileActiveIndex(items, previousItems, activeCategoryIndex.value); }); onMounted(() => { document.addEventListener("pointerdown", handleDocumentInteraction); diff --git a/tests/appCatalogCombobox.spec.ts b/tests/appCatalogCombobox.spec.ts index ec96841..0b2825f 100644 --- a/tests/appCatalogCombobox.spec.ts +++ b/tests/appCatalogCombobox.spec.ts @@ -50,4 +50,68 @@ describe("AppCatalogCombobox responsive selected value", () => { expect(wrapper.find(".app-catalog-selected-value").exists()).toBe(false); expect(wrapper.get('input[role="combobox"]').element.value).toBe(""); }); + it("keeps an open list stable across hover and non-empty option refreshes", async () => { + const wrapper = mount(AppCatalogCombobox, { + attachTo: document.body, + props: { label: "Показатели", options, selectedIds: ["long"], customText: "", multiple: true }, + }); + const input = wrapper.get('input[role="combobox"]'); + const toggle = wrapper.get(".app-catalog-toggle"); + await toggle.trigger("click"); + await input.setValue("о"); + await input.trigger("keydown", { key: "ArrowDown" }); + input.element.focus(); + const listbox = wrapper.get('[role="listbox"]'); + listbox.element.scrollTop = 24; + + await toggle.trigger("pointerover"); + await wrapper.setProps({ options: options.map((option) => ({ ...option })) }); + + expect(input.attributes("aria-expanded")).toBe("true"); + expect(input.element.value).toBe("о"); + expect(wrapper.get(".app-catalog-option.active").text()).toBe(longLabel); + expect(listbox.element.scrollTop).toBe(24); + expect(document.activeElement).toBe(input.element); + + await wrapper.setProps({ options: [{ id: "new", label: "Новое значение" }, ...options] }); + + expect(input.attributes("aria-expanded")).toBe("true"); + expect(input.element.value).toBe("о"); + expect(wrapper.get(".app-catalog-option.active").text()).toBe(longLabel); + expect(listbox.element.scrollTop).toBe(24); + expect(document.activeElement).toBe(input.element); + + await wrapper.setProps({ options: [] }); + + expect(input.attributes("aria-expanded")).toBe("false"); + expect(wrapper.find('[role="listbox"]').exists()).toBe(false); + expect(toggle.attributes("disabled")).toBeDefined(); + wrapper.unmount(); + }); + + it("returns to the category root when an open two-level category disappears", async () => { + const wrapper = mount(AppCatalogCombobox, { + attachTo: document.body, + props: { + label: "Диагноз", + groups: [{ id: "first", label: "Первая категория", options: [{ id: "one", label: "Первый" }] }], + selectedIds: [], + customText: "", + twoLevel: true, + }, + }); + const input = wrapper.get('input[role="combobox"]'); + await wrapper.get(".app-catalog-toggle").trigger("click"); + await wrapper.get(".app-catalog-category").trigger("click"); + expect(wrapper.get(".app-catalog-level-heading").text()).toContain("Первая категория"); + + await wrapper.setProps({ + groups: [{ id: "second", label: "Вторая категория", options: [{ id: "two", label: "Второй" }] }], + }); + + expect(input.attributes("aria-expanded")).toBe("true"); + expect(wrapper.get(".app-catalog-level-prompt").text()).toBe("Выберите категорию"); + expect(wrapper.get(".app-catalog-category.active").text()).toContain("Вторая категория"); + wrapper.unmount(); + }); });