From 779593f73a8b20784a7f94d685696fb1ef463f16 Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Mon, 10 Mar 2025 23:38:21 +0000 Subject: [PATCH] fix(core): Improve error handling, logging, and test suite; update dependency versions --- changelog.md | 7 + package.json | 8 +- pnpm-lock.yaml | 989 ++++++++++++++++++++++++++++++++--- test/test.ts | 133 ++++- ts/00_commitinfo_data.ts | 2 +- ts/classes.processmonitor.ts | 107 +++- ts/classes.processwrapper.ts | 58 +- ts/classes.tspm.ts | 326 +++++++++--- ts/cli.ts | 109 +++- ts/paths.ts | 4 +- ts/plugins.ts | 3 + ts/utils.errorhandler.ts | 138 +++++ 12 files changed, 1648 insertions(+), 236 deletions(-) create mode 100644 ts/utils.errorhandler.ts diff --git a/changelog.md b/changelog.md index a36fce2..16b0096 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2025-03-10 - 1.5.1 - fix(core) +Improve error handling, logging, and test suite; update dependency versions + +- Updated devDependencies versions in package.json (@git.zone/tsbuild, @push.rocks/tapbundle, and @push.rocks/smartdaemon) +- Refactored error handling and enhanced logging in ProcessMonitor and ProcessWrapper modules +- Improved test structure by adding clear module import tests and usage examples in test files + ## 2025-03-04 - 1.5.0 - feat(cli) Enhance CLI with new process management commands diff --git a/package.json b/package.json index a05406f..77dd453 100644 --- a/package.json +++ b/package.json @@ -18,18 +18,18 @@ "tspm": "./cli.js" }, "devDependencies": { - "@git.zone/tsbuild": "^2.1.25", + "@git.zone/tsbuild": "^2.2.6", "@git.zone/tsbundle": "^2.0.5", "@git.zone/tsrun": "^1.2.46", "@git.zone/tstest": "^1.0.44", - "@push.rocks/tapbundle": "^5.0.15", - "@types/node": "^22.13.8" + "@push.rocks/tapbundle": "^5.5.9", + "@types/node": "^22.13.10" }, "dependencies": { "@push.rocks/npmextra": "^5.1.2", "@push.rocks/projectinfo": "^5.0.2", "@push.rocks/smartcli": "^4.0.11", - "@push.rocks/smartdaemon": "^2.0.6", + "@push.rocks/smartdaemon": "^2.0.8", "@push.rocks/smartpath": "^5.0.18", "pidusage": "^4.0.0", "ps-tree": "^1.2.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 97a54fa..941ba92 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: ^4.0.11 version: 4.0.11 '@push.rocks/smartdaemon': - specifier: ^2.0.6 - version: 2.0.6 + specifier: ^2.0.8 + version: 2.0.8 '@push.rocks/smartpath': specifier: ^5.0.18 version: 5.0.18 @@ -31,8 +31,8 @@ importers: version: 1.2.0 devDependencies: '@git.zone/tsbuild': - specifier: ^2.1.25 - version: 2.2.1 + specifier: ^2.2.6 + version: 2.2.6 '@git.zone/tsbundle': specifier: ^2.0.5 version: 2.2.5 @@ -43,14 +43,18 @@ importers: specifier: ^1.0.44 version: 1.0.96(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4)(typescript@5.7.3) '@push.rocks/tapbundle': - specifier: ^5.0.15 - version: 5.5.6(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4) + specifier: ^5.5.9 + version: 5.5.9(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4) '@types/node': - specifier: ^22.13.8 - version: 22.13.8 + specifier: ^22.13.10 + version: 22.13.10 packages: + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + '@api.global/typedrequest-interfaces@2.0.2': resolution: {integrity: sha512-D+mkr4IiUZ/eUgrdp5jXjBKOW/iuMcl0z2ZLQsLLypKX/psFGD3viZJ58FNRa+/1OSM38JS5wFyoWl8oPEFLrw==} @@ -233,14 +237,164 @@ packages: resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.9': + resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.26.9': + resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.26.5': + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.25.9': resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.26.9': + resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.26.9': + resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.25.9': + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/runtime@7.23.4': resolution: {integrity: sha512-2Yv65nlWnWlSpe3fXEyX5i7fx5kIKo4Qbcj+hMO0odwaneFjfXw5fdum+4yL20O0QiaHpia0cYQ9xpNMqrBwHg==} engines: {node: '>=6.9.0'} + '@babel/template@7.26.9': + resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.26.9': + resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.26.9': + resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} + engines: {node: '>=6.9.0'} + '@cloudflare/workers-types@4.20250224.0': resolution: {integrity: sha512-j6ZwQ5G2moQRaEtGI2u5TBQhVXv/XwOS5jfBAheZHcpCM07zm8j0i8jZHHLq/6VA8e6VRjKohOyj5j6tZ1KHLQ==} @@ -566,8 +720,8 @@ packages: '@esm-bundle/chai@4.3.4-fix.0': resolution: {integrity: sha512-26SKdM4uvDWlY8/OOOxSB1AqQWeBosCX3wRYUZO7enTAj03CtVxIiCimYVG2WpULcyV51qapK4qTovwkUr5Mlw==} - '@git.zone/tsbuild@2.2.1': - resolution: {integrity: sha512-qvyhpRDBm+ZtRJjpx9zgmSBNgdvjkbJ66TxjmFGm0kjT9i/QK2nvfwJXf0CwRfuRQwHhZbl/wYO/dChYkwi0fA==} + '@git.zone/tsbuild@2.2.6': + resolution: {integrity: sha512-6CZ0wqtW/+WXzoHxzNPIKVzPjTColxVoY+TpzlIaz01WktiNr/oeJAfYXdQIVTVYpJs1n9tZ3fwKP6l3LAPAlQ==} hasBin: true '@git.zone/tsbundle@2.2.5': @@ -597,18 +751,64 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/expect-utils@29.7.0': resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/expect@29.7.0': + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/globals@29.7.0': + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/schemas@29.6.3': resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/types@29.6.3': resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@koa/router@9.4.0': resolution: {integrity: sha512-dOOXgzqaDoHu5qqMEPLKEgLz5CeIA7q8+1W62mCvFVCOqeC71UoTGJ4u1xUSOpIl2J1x2pqrNULkFteUeZW3/A==} engines: {node: '>= 8.0.0'} @@ -752,8 +952,8 @@ packages: '@push.rocks/smartcrypto@2.0.4': resolution: {integrity: sha512-1+/5bsjyataf5uUkUNnnVXGRAt+gHVk1KDzozjTqgqJxHvQk1d9fVDohL6CxUhUucTPtu5VR5xNBiV8YCDuGyw==} - '@push.rocks/smartdaemon@2.0.6': - resolution: {integrity: sha512-yFbZIT8Vb8fCdihM+kUnSluYmTzfARuZEs7Mbh+GjNJ9H+gbfyCt30BKocsPBUDkuliSAv/RlbYLILACNZlX8w==} + '@push.rocks/smartdaemon@2.0.8': + resolution: {integrity: sha512-92qCS8XqGhQrCBDrz5L+WrWzlAggy93mXacVx9zEzGK41QwxRxZSMfxEMTxq4FO9YD4Kymffesav7S3ivCuJeQ==} '@push.rocks/smartdata@5.2.12': resolution: {integrity: sha512-vp0nz1P/SJcoFhyfZoewPbFSameWnuMuCkySvnb41TcCi1PFHA//KOYImdti/qURSOYwVoTKboDrnx1/ffHp7g==} @@ -767,8 +967,8 @@ packages: '@push.rocks/smartexit@1.0.23': resolution: {integrity: sha512-WmwKYcwbHBByoABhHHB+PAjr5475AtD/xBh1mDcqPrFsOOUOZq3BBUdpq25wI3ccu/SZB5IwaimiVzadls6HkA==} - '@push.rocks/smartexpect@1.4.0': - resolution: {integrity: sha512-1DwLgNXz5mp8etpyBXftvQXsRYNke5eMZxi855NwStjvx/LcAMwA+95GqbobjGb3DS/4xwxcuM15Gy0+UBwF6Q==} + '@push.rocks/smartexpect@1.6.1': + resolution: {integrity: sha512-NFQXEPkGiMNxyvFwKyzDWe3ADYdf8KNvIcV7TGNZZT3uPQtk65te4Q+a1cWErjP/61yE9XdYiQA66QQp+TV9IQ==} '@push.rocks/smartfeed@1.0.11': resolution: {integrity: sha512-02uhXxQamgfBo3T12FsAdfyElnpoWuDUb08B2AE60DbIaukVx/7Mi17xwobApY1flNSr5StZDt8N8vxPhBhIXw==} @@ -908,8 +1108,8 @@ packages: '@push.rocks/smartyaml@2.0.5': resolution: {integrity: sha512-tBcf+HaOIfeEsTMwgUZDtZERCxXQyRsWO8Ar5DjBdiSRchbhVGZQEBzXswMS0W5ZoRenjgPK+4tPW3JQGRTfbg==} - '@push.rocks/tapbundle@5.5.6': - resolution: {integrity: sha512-V6u+nZwt4fNccxbm3ztZgHr/QAj/uKhaaOUFgtaae0jzYdds4jNEI+mXLpfXuNMgm7Nx93Lk5XUxWKTI8drjNw==} + '@push.rocks/tapbundle@5.5.9': + resolution: {integrity: sha512-eDGklv1v+VA5uP2LzaYGjRq+PTi2NlvyOqBUKTw6LvtQOQQFDmmdKaUkPICz1SkkZTtpUHqNaTE+zpF/jk8K7g==} '@push.rocks/taskbuffer@3.1.7': resolution: {integrity: sha512-QktGVJPucqQmW/QNGnscf4FAigT1H7JWKFGFdRuDEaOHKFh9qN+PXG3QY7DtZ4jfXdGLxPN4yAufDuPSAJYFnw==} @@ -1052,6 +1252,12 @@ packages: resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} engines: {node: '>=14.16'} + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@smithy/abort-controller@4.0.1': resolution: {integrity: sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==} engines: {node: '>=18.0.0'} @@ -1289,6 +1495,9 @@ packages: '@tsclass/tsclass@4.4.0': resolution: {integrity: sha512-/T3qmxj28yRMM+0x9UtyBmrsJ66flviQEDg3M4kwmWuZQgbrDACa6JXdA0ieqfmuPOXDJRRDKcyKaKvKi2EdwA==} + '@tsclass/tsclass@4.4.3': + resolution: {integrity: sha512-Vhp+B1UsYlwXLhIeds++CXEeCwFgRzpput4YNM7Qyhr+UQgIMFRFAs2HSI3jEE5r9c1hR9G6MkSxi2U/CLyiaA==} + '@types/accepts@1.3.7': resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} @@ -1307,8 +1516,8 @@ packages: '@types/chai@4.3.20': resolution: {integrity: sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==} - '@types/chai@5.0.1': - resolution: {integrity: sha512-5T8ajsg3M/FOncpLYW7sdOcD6yf4+722sze/tc4KQV0P8Z2rAr3SAuHCIkYmYpt8VbcQlnz8SxlOlPQYefe4cA==} + '@types/chai@5.2.0': + resolution: {integrity: sha512-FWnQYdrG9FAC8KgPVhDFfrPL1FBsL3NtIt2WsxKvwu/61K6HiuDF3xAb7c7w/k9ML2QOUHcwTgU7dKLFPK6sBg==} '@types/clean-css@4.2.11': resolution: {integrity: sha512-Y8n81lQVTAfP2TOdtJJEsCoYl1AnOkqDqMvXb9/7pfgZZ7r8YrEyurrAvAoAjHOGXKRybay+5CsExqIH6liccw==} @@ -1377,6 +1586,9 @@ packages: '@types/glob@8.1.0': resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + '@types/gunzip-maybe@1.4.2': resolution: {integrity: sha512-2uqXZg1jTCKE1Pjbab8qb74+f2+i9h/jz8rQ+jRR+zaNJF75zWwrpbX8/TjF4m56m3KFOg9umHdCJ074KwiVxg==} @@ -1443,8 +1655,8 @@ packages: '@types/node-forge@1.3.11': resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} - '@types/node@22.13.8': - resolution: {integrity: sha512-G3EfaZS+iOGYWLLRCEAXdWK9my08oHNZ+FHluRiggIYJPOXzhOiDgpVCUHaUvyIC5/fj7C/p637jdzC666AOKQ==} + '@types/node@22.13.10': + resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==} '@types/parse5@6.0.3': resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} @@ -1617,6 +1829,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -1647,13 +1863,22 @@ packages: asynckit@0.4.0: resolution: {integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=} - axe-core@4.10.2: - resolution: {integrity: sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==} + axe-core@4.10.3: + resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} engines: {node: '>=4'} b4a@1.6.7: resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -1722,6 +1947,14 @@ packages: browserify-zlib@0.1.4: resolution: {integrity: sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=} + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + bson@4.7.2: resolution: {integrity: sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==} engines: {node: '>=6.9.0'} @@ -1777,6 +2010,10 @@ packages: resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} engines: {node: '>= 0.4'} + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -1784,10 +2021,17 @@ packages: camel-case@3.0.0: resolution: {integrity: sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=} + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} + caniuse-lite@1.0.30001702: + resolution: {integrity: sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA==} + ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -2120,6 +2364,9 @@ packages: ee-first@1.1.1: resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=} + electron-to-chromium@1.5.113: + resolution: {integrity: sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2319,6 +2566,9 @@ packages: fault@2.0.1: resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fd-slicer@1.1.0: resolution: {integrity: sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=} @@ -2429,6 +2679,10 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -2437,6 +2691,10 @@ packages: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + get-port@5.1.1: resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} engines: {node: '>=8'} @@ -2480,6 +2738,10 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -2617,6 +2879,10 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + imurmurhash@0.1.4: + resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=} + engines: {node: '>=0.8.19'} + indent-string@5.0.0: resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} engines: {node: '>=12'} @@ -2768,6 +3034,10 @@ packages: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + istanbul-lib-report@3.0.1: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} @@ -2791,6 +3061,10 @@ packages: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-matcher-utils@29.7.0: resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2799,10 +3073,26 @@ packages: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-util@29.7.0: resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} @@ -2820,12 +3110,22 @@ packages: jsbn@1.1.0: resolution: {integrity: sha1-sBMHyym2GKHtJux56RH4A8TaAEA=} + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + jsonfile@4.0.0: resolution: {integrity: sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=} @@ -2966,6 +3266,9 @@ packages: resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} engines: {node: 20 || >=22} + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@7.18.3: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} @@ -2988,6 +3291,9 @@ packages: make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + map-stream@0.1.0: resolution: {integrity: sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=} @@ -3255,8 +3561,8 @@ packages: resolution: {integrity: sha512-mLV7SEiov2LHleRJPMPrK2PMyhXFZt2UQLC4VD4pnth3jMjYKHhtqfwwkkvS/NXuo/Fp3vbhaNcXrIDaLRb9Tg==} engines: {node: '>=12.9.0'} - mongodb@6.14.0: - resolution: {integrity: sha512-AlM6alTx98vcnk/jMMmoYuBrm4qpe1/VrbwvL2SXEHjdtJ1ZbVZmrpyjUx9mqS94e9HcemzpLn+CxzhmT7b0uw==} + mongodb@6.14.2: + resolution: {integrity: sha512-kMEHNo0F3P6QKDq17zcDuPeaywK/YaJVCEQRzPF3TOM/Bl9MFg64YE5Tu7ifj37qZJMhwU1tl2Ioivws5gRG5Q==} engines: {node: '>=16.20.1'} peerDependencies: '@aws-sdk/credential-providers': ^3.188.0 @@ -3291,8 +3597,8 @@ packages: nanocolors@0.2.13: resolution: {integrity: sha512-0n3mSAQLPpGLV9ORXT5+C/D4mwew7Ebws69Hx4E2sgz2ZA5+32Q80B9tL8PbL7XHnRDiAxH/pnrUJ9a4fkTNTA==} - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + nanoid@3.3.9: + resolution: {integrity: sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -3301,6 +3607,9 @@ packages: engines: {node: ^14 || ^16 || >=18} hasBin: true + natural-compare@1.4.0: + resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} + negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} @@ -3320,10 +3629,20 @@ packages: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} + node-int64@0.4.0: + resolution: {integrity: sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + normalize-newline@4.1.0: resolution: {integrity: sha512-ff4jKqMI8Xl50/4Mms/9jPobzAV/UK+kXG2XJ/7AqOmxIx8mqfqTIHYxuAnEgJ2AQeBbLnlbmZ5+38Y9A0w/YA==} engines: {node: '>=12'} + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + normalize-url@8.0.1: resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} engines: {node: '>=14.16'} @@ -3530,6 +3849,10 @@ packages: resolution: {integrity: sha512-56ZMC0j7SCsMMLdOoUg12VZCfj/+ZO+yfOSjaNCRrmZZr6GLbN2X/Ui56T15dI8NhiHckaw5X2pvyfAomanwqQ==} engines: {node: '>=4.0.0'} + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -3698,6 +4021,10 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + resolve-path@1.4.0: resolution: {integrity: sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==} engines: {node: '>= 0.8'} @@ -3969,6 +4296,10 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + sweet-scroll@4.0.0: resolution: {integrity: sha512-mR6fRsAQANtm3zpzhUE73KAOt2aT4ZsWzNSggiEsSqdO6Zh4gM7ioJG81EngrZEl0XAc3ZvzEfhxggOoEBc8jA==} @@ -3995,6 +4326,10 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + text-decoder@1.2.3: resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} @@ -4016,6 +4351,9 @@ packages: tiny-worker@2.3.0: resolution: {integrity: sha512-pJ70wq5EAqTAEl9IkGzA+fN0836rycEuz2Cn6yeZ6FRzlVS5IDOkFHpIoEsksPRQV34GDqXm65+OlnZqUSyK2g==} + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4071,6 +4409,10 @@ packages: turndown@7.2.0: resolution: {integrity: sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==} + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} @@ -4083,6 +4425,10 @@ packages: resolution: {integrity: sha512-3T/PUdKTCnkUmhQU6FFJEHsLwadsRegktX3TNHk+2JJB9HlA8gp1/VXblXVDI93kSnXF2rdPx0GMbHtJIV2LPg==} engines: {node: '>=16'} + type-fest@4.37.0: + resolution: {integrity: sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==} + engines: {node: '>=16'} + type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -4140,6 +4486,12 @@ packages: resolution: {integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=} engines: {node: '>= 0.8'} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + upper-case@1.1.3: resolution: {integrity: sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=} @@ -4168,6 +4520,9 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -4217,6 +4572,10 @@ packages: wrappy@1.0.2: resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + ws@7.5.10: resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} engines: {node: '>=8.3.0'} @@ -4293,6 +4652,9 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -4319,6 +4681,11 @@ packages: snapshots: + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + '@api.global/typedrequest-interfaces@2.0.2': {} '@api.global/typedrequest-interfaces@3.0.19': {} @@ -4943,12 +5310,189 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/compat-data@7.26.8': {} + + '@babel/core@7.26.9': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helpers': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + convert-source-map: 2.0.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.26.9': + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.26.5': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.26.5': {} + + '@babel/helper-string-parser@7.25.9': {} + '@babel/helper-validator-identifier@7.25.9': {} + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helpers@7.26.9': + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + + '@babel/parser@7.26.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/runtime@7.23.4': dependencies: regenerator-runtime: 0.14.1 + '@babel/template@7.26.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + + '@babel/traverse@7.26.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.26.9': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@cloudflare/workers-types@4.20250224.0': {} '@colors/colors@1.6.0': {} @@ -5162,7 +5706,7 @@ snapshots: dependencies: '@types/chai': 4.3.20 - '@git.zone/tsbuild@2.2.1': + '@git.zone/tsbuild@2.2.6': dependencies: '@git.zone/tspublish': 1.9.1 '@push.rocks/early': 4.0.4 @@ -5225,7 +5769,7 @@ snapshots: '@push.rocks/smartlog': 3.0.7 '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartshell': 3.2.3 - '@push.rocks/tapbundle': 5.5.6(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4) + '@push.rocks/tapbundle': 5.5.9(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4) '@types/ws': 8.5.14 figures: 6.1.0 ws: 8.18.1 @@ -5262,23 +5806,102 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + jest-mock: 29.7.0 + '@jest/expect-utils@29.7.0': dependencies: jest-get-type: 29.6.3 + '@jest/expect@29.7.0': + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 22.13.10 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/globals@29.7.0': + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + '@jest/schemas@29.6.3': dependencies: '@sinclair/typebox': 0.27.8 + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.26.9 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + '@jest/types@29.6.3': dependencies: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/yargs': 17.0.33 chalk: 4.1.2 + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@koa/router@9.4.0': dependencies: debug: 4.4.0 @@ -5433,7 +6056,7 @@ snapshots: '@push.rocks/smartstring': 4.0.15 '@push.rocks/smartunique': 3.0.9 '@push.rocks/taskbuffer': 3.1.7 - '@tsclass/tsclass': 4.4.0 + '@tsclass/tsclass': 4.4.3 transitivePeerDependencies: - aws-crt @@ -5455,7 +6078,7 @@ snapshots: '@pushrocks/smartjson': 4.0.6 '@pushrocks/smartpath': 5.0.5 '@pushrocks/smartpromise': 3.1.10 - '@tsclass/tsclass': 4.4.0 + '@tsclass/tsclass': 4.4.3 mongodb: 4.17.2 transitivePeerDependencies: - aws-crt @@ -5563,7 +6186,7 @@ snapshots: '@types/node-forge': 1.3.11 node-forge: 1.3.1 - '@push.rocks/smartdaemon@2.0.6': + '@push.rocks/smartdaemon@2.0.8': dependencies: '@push.rocks/lik': 6.1.0 '@push.rocks/smartfile': 11.2.0 @@ -5586,8 +6209,8 @@ snapshots: '@push.rocks/smarttime': 4.1.1 '@push.rocks/smartunique': 3.0.9 '@push.rocks/taskbuffer': 3.1.7 - '@tsclass/tsclass': 4.4.0 - mongodb: 6.14.0(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4) + '@tsclass/tsclass': 4.4.3 + mongodb: 6.14.2(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4) transitivePeerDependencies: - '@aws-sdk/credential-providers' - '@mongodb-js/zstd' @@ -5614,7 +6237,7 @@ snapshots: '@push.rocks/smartpromise': 4.2.3 tree-kill: 1.2.2 - '@push.rocks/smartexpect@1.4.0': + '@push.rocks/smartexpect@1.6.1': dependencies: '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartpromise': 4.2.3 @@ -5867,7 +6490,7 @@ snapshots: '@push.rocks/smartbucket': 3.3.7 '@push.rocks/smartfile': 11.2.0 '@push.rocks/smartpath': 5.0.18 - '@tsclass/tsclass': 4.4.0 + '@tsclass/tsclass': 4.4.3 '@types/s3rver': 3.7.4 s3rver: 3.7.1 transitivePeerDependencies: @@ -6004,15 +6627,16 @@ snapshots: '@types/js-yaml': 3.12.10 js-yaml: 3.14.1 - '@push.rocks/tapbundle@5.5.6(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4)': + '@push.rocks/tapbundle@5.5.9(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4)': dependencies: + '@jest/globals': 29.7.0 '@open-wc/testing': 4.0.0 '@push.rocks/consolecolor': 2.0.2 '@push.rocks/qenv': 6.1.0 '@push.rocks/smartcrypto': 2.0.4 '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartenv': 5.0.12 - '@push.rocks/smartexpect': 1.4.0 + '@push.rocks/smartexpect': 1.6.1 '@push.rocks/smartfile': 11.2.0 '@push.rocks/smartjson': 5.0.20 '@push.rocks/smartmongo': 2.0.10(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4) @@ -6259,6 +6883,14 @@ snapshots: '@sindresorhus/is@5.6.0': {} + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + '@smithy/abort-controller@4.0.1': dependencies: '@smithy/types': 4.1.0 @@ -6614,42 +7246,46 @@ snapshots: dependencies: type-fest: 4.36.0 + '@tsclass/tsclass@4.4.3': + dependencies: + type-fest: 4.37.0 + '@types/accepts@1.3.7': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/babel__code-frame@7.0.6': {} '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/buffer-json@2.0.3': {} '@types/chai-dom@1.11.3': dependencies: - '@types/chai': 5.0.1 + '@types/chai': 5.2.0 '@types/chai@4.3.20': {} - '@types/chai@5.0.1': + '@types/chai@5.2.0': dependencies: '@types/deep-eql': 4.0.2 '@types/clean-css@4.2.11': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 source-map: 0.6.1 '@types/co-body@6.1.3': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/qs': 6.9.18 '@types/connect@3.4.38': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/content-disposition@0.5.8': {} @@ -6662,11 +7298,11 @@ snapshots: '@types/connect': 3.4.38 '@types/express': 5.0.0 '@types/keygrip': 1.0.6 - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/cors@2.8.17': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/debounce@1.2.4': {} @@ -6680,14 +7316,14 @@ snapshots: '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/qs': 6.9.18 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 '@types/express-serve-static-core@5.0.6': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/qs': 6.9.18 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -6712,30 +7348,34 @@ snapshots: '@types/from2@2.3.5': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/fs-extra@9.0.13': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/glob@8.1.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.13.8 + '@types/node': 22.13.10 + + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 22.13.10 '@types/gunzip-maybe@1.4.2': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/hast@3.0.4': dependencies: @@ -6769,7 +7409,7 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/keygrip@1.0.6': {} @@ -6786,7 +7426,7 @@ snapshots: '@types/http-errors': 2.0.4 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/mdast@4.0.4': dependencies: @@ -6804,9 +7444,9 @@ snapshots: '@types/node-forge@1.3.11': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 - '@types/node@22.13.8': + '@types/node@22.13.10': dependencies: undici-types: 6.20.0 @@ -6824,24 +7464,24 @@ snapshots: '@types/s3rver@3.7.4': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/semver@7.5.8': {} '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/send': 0.17.4 '@types/sinon-chai@3.2.12': dependencies: - '@types/chai': 5.0.1 + '@types/chai': 5.2.0 '@types/sinon': 17.0.4 '@types/sinon@17.0.4': @@ -6856,11 +7496,11 @@ snapshots: '@types/tar-stream@2.2.3': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/through2@2.0.41': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/triple-beam@1.3.5': {} @@ -6884,18 +7524,18 @@ snapshots: '@types/whatwg-url@8.2.2': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/webidl-conversions': 7.0.3 '@types/which@3.0.4': {} '@types/ws@7.4.7': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/ws@8.5.14': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 '@types/yargs-parser@21.0.3': {} @@ -6905,7 +7545,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.13.8 + '@types/node': 22.13.10 optional: true '@ungap/structured-clone@1.3.0': {} @@ -6977,7 +7617,7 @@ snapshots: istanbul-reports: 3.1.7 log-update: 4.0.0 nanocolors: 0.2.13 - nanoid: 3.3.8 + nanoid: 3.3.9 open: 8.4.2 picomatch: 2.3.1 source-map: 0.7.4 @@ -7030,6 +7670,11 @@ snapshots: ansi-styles@6.2.1: {} + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -7054,10 +7699,39 @@ snapshots: asynckit@0.4.0: {} - axe-core@4.10.2: {} + axe-core@4.10.3: {} b4a@1.6.7: {} + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.26.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.9) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.9) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.9) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.9) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.9) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.9) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.9) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.9) + bail@2.0.2: {} balanced-match@1.0.2: {} @@ -7144,6 +7818,17 @@ snapshots: dependencies: pako: 0.2.9 + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001702 + electron-to-chromium: 1.5.113 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + bson@4.7.2: dependencies: buffer: 5.7.1 @@ -7206,6 +7891,11 @@ snapshots: call-bind-apply-helpers: 1.0.2 get-intrinsic: 1.3.0 + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + callsites@3.1.0: {} camel-case@3.0.0: @@ -7213,13 +7903,17 @@ snapshots: no-case: 2.3.2 upper-case: 1.1.3 + camelcase@5.3.1: {} + camelcase@6.3.0: {} + caniuse-lite@1.0.30001702: {} + ccount@2.0.1: {} chai-a11y-axe@1.5.0: dependencies: - axe-core: 4.10.2 + axe-core: 4.10.3 chalk@2.4.2: dependencies: @@ -7500,6 +8194,8 @@ snapshots: ee-first@1.1.1: {} + electron-to-chromium@1.5.113: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -7532,7 +8228,7 @@ snapshots: dependencies: '@types/cookie': 0.4.1 '@types/cors': 2.8.17 - '@types/node': 22.13.8 + '@types/node': 22.13.10 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.4.2 @@ -7786,6 +8482,10 @@ snapshots: dependencies: format: 0.2.2 + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + fd-slicer@1.1.0: dependencies: pend: 1.2.0 @@ -7903,6 +8603,8 @@ snapshots: function-bind@1.1.2: {} + gensync@1.0.0-beta.2: {} + get-caller-file@2.0.5: {} get-intrinsic@1.3.0: @@ -7918,6 +8620,8 @@ snapshots: hasown: 2.0.2 math-intrinsics: 1.1.0 + get-package-type@0.1.0: {} + get-port@5.1.1: {} get-proto@1.0.1: @@ -7979,6 +8683,8 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 + globals@11.12.0: {} + globby@11.1.0: dependencies: array-union: 2.1.0 @@ -8165,6 +8871,8 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + imurmurhash@0.1.4: {} + indent-string@5.0.0: {} inflation@2.1.0: {} @@ -8214,7 +8922,7 @@ snapshots: is-generator-function@1.1.0: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 get-proto: 1.0.1 has-tostringtag: 1.0.2 safe-regex-test: 1.1.0 @@ -8248,7 +8956,7 @@ snapshots: is-regex@1.2.1: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 gopd: 1.2.0 has-tostringtag: 1.0.2 hasown: 2.0.2 @@ -8277,6 +8985,16 @@ snapshots: istanbul-lib-coverage@3.2.2: {} + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.26.9 + '@babel/parser': 7.26.9 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + istanbul-lib-report@3.0.1: dependencies: istanbul-lib-coverage: 3.2.2 @@ -8307,6 +9025,22 @@ snapshots: jest-get-type@29.6.3: {} + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.13.10 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + jest-matcher-utils@29.7.0: dependencies: chalk: 4.1.2 @@ -8326,15 +9060,55 @@ snapshots: slash: 3.0.0 stack-utils: 2.0.6 + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + jest-util: 29.7.0 + + jest-regex-util@29.6.3: {} + + jest-snapshot@29.7.0: + dependencies: + '@babel/core': 7.26.9 + '@babel/generator': 7.26.9 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.9) + '@babel/types': 7.26.9 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.9) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.13.8 + '@types/node': 22.13.10 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 picomatch: 2.3.1 + jest-worker@29.7.0: + dependencies: + '@types/node': 22.13.10 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + js-base64@3.7.7: {} js-tokens@4.0.0: {} @@ -8350,10 +9124,14 @@ snapshots: jsbn@1.1.0: {} + jsesc@3.1.0: {} + json-buffer@3.0.1: {} json-parse-even-better-errors@2.3.1: {} + json5@2.2.3: {} + jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 @@ -8528,6 +9306,10 @@ snapshots: lru-cache@11.0.2: {} + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + lru-cache@7.18.3: {} lru-cache@8.0.5: {} @@ -8546,6 +9328,10 @@ snapshots: make-error@1.3.6: {} + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + map-stream@0.1.0: {} markdown-table@3.0.4: {} @@ -9003,7 +9789,7 @@ snapshots: transitivePeerDependencies: - aws-crt - mongodb@6.14.0(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4): + mongodb@6.14.2(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4): dependencies: '@mongodb-js/saslprep': 1.2.0 bson: 6.10.3 @@ -9018,10 +9804,12 @@ snapshots: nanocolors@0.2.13: {} - nanoid@3.3.8: {} + nanoid@3.3.9: {} nanoid@4.0.2: {} + natural-compare@1.4.0: {} + negotiator@0.6.3: {} netmask@2.0.2: {} @@ -9038,10 +9826,16 @@ snapshots: node-forge@1.3.1: {} + node-int64@0.4.0: {} + + node-releases@2.0.19: {} + normalize-newline@4.1.0: dependencies: replace-buffer: 1.2.1 + normalize-path@3.0.0: {} + normalize-url@8.0.1: {} npm-run-path@4.0.1: @@ -9224,6 +10018,8 @@ snapshots: ping@0.4.4: {} + pirates@4.0.6: {} + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -9451,6 +10247,8 @@ snapshots: resolve-from@4.0.0: {} + resolve-from@5.0.0: {} + resolve-path@1.4.0: dependencies: http-errors: 1.6.3 @@ -9508,7 +10306,7 @@ snapshots: safe-regex-test@1.1.0: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 es-errors: 1.3.0 is-regex: 1.2.1 @@ -9785,6 +10583,10 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + sweet-scroll@4.0.0: {} symbol-tree@3.2.4: {} @@ -9824,6 +10626,12 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + text-decoder@1.2.3: dependencies: b4a: 1.6.7 @@ -9856,6 +10664,8 @@ snapshots: dependencies: esm: 3.2.25 + tmpl@1.0.5: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -9902,12 +10712,16 @@ snapshots: dependencies: '@mixmark-io/domino': 2.2.0 + type-detect@4.0.8: {} + type-fest@0.21.3: {} type-fest@2.19.0: {} type-fest@4.36.0: {} + type-fest@4.37.0: {} + type-is@1.6.18: dependencies: media-typer: 0.3.0 @@ -9964,6 +10778,12 @@ snapshots: unpipe@1.0.0: {} + update-browserslist-db@1.1.3(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + upper-case@1.1.3: {} url@0.11.4: @@ -9989,6 +10809,10 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + webidl-conversions@7.0.0: {} whatwg-mimetype@3.0.0: {} @@ -10051,6 +10875,11 @@ snapshots: wrappy@1.0.2: {} + write-file-atomic@4.0.2: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + ws@7.5.10: {} ws@8.11.0: {} @@ -10083,6 +10912,8 @@ snapshots: y18n@5.0.8: {} + yallist@3.1.1: {} + yallist@4.0.0: {} yargs-parser@21.1.1: {} diff --git a/test/test.ts b/test/test.ts index 14e8a3a..c6c0eb4 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1,27 +1,124 @@ import { expect, expectAsync, tap } from '@push.rocks/tapbundle'; import * as tspm from '../ts/index.js'; +import { join } from 'path'; -tap.test('first test', async () => { - console.log(tspm); +// Basic module import test +tap.test('module import test', async () => { + console.log('Imported modules:', Object.keys(tspm)); + expect(tspm.ProcessMonitor).toBeTypeOf('function'); + expect(tspm.Tspm).toBeTypeOf('function'); +}); + +// ProcessMonitor test +tap.test('ProcessMonitor test', async () => { + const config: tspm.IMonitorConfig = { + name: 'Test Monitor', + projectDir: process.cwd(), + command: 'echo "Test process running"', + memoryLimitBytes: 50 * 1024 * 1024, // 50MB + monitorIntervalMs: 1000, + }; + + const monitor = new tspm.ProcessMonitor(config); + + // Test monitor creation + expect(monitor).toBeInstanceOf(tspm.ProcessMonitor); + + // We won't actually start it in tests to avoid side effects + // but we can test the API + expect(monitor.start).toBeInstanceOf('function'); + expect(monitor.stop).toBeInstanceOf('function'); + expect(monitor.getLogs).toBeInstanceOf('function'); +}); + +// Tspm class test +tap.test('Tspm class test', async () => { + const tspmInstance = new tspm.Tspm(); + + expect(tspmInstance).toBeInstanceOf(tspm.Tspm); + expect(tspmInstance.start).toBeInstanceOf('function'); + expect(tspmInstance.stop).toBeInstanceOf('function'); + expect(tspmInstance.restart).toBeInstanceOf('function'); + expect(tspmInstance.list).toBeInstanceOf('function'); + expect(tspmInstance.describe).toBeInstanceOf('function'); + expect(tspmInstance.getLogs).toBeInstanceOf('function'); }); tap.start(); -// Example usage: -const config: tspm.IMonitorConfig = { - name: 'Project XYZ Monitor', // Identifier for the instance - projectDir: '/path/to/your/project', // Set the project directory here - command: 'npm run xyz', // Full command string (no need for args) - memoryLimitBytes: 500 * 1024 * 1024, // 500 MB memory limit - monitorIntervalMs: 5000, // Check memory usage every 5 seconds -}; +// ==================================================== +// Example usage (this part is not executed in tests) +// ==================================================== -const monitor = new tspm.ProcessMonitor(config); -monitor.start(); +// Example 1: Using ProcessMonitor directly +function exampleUsingProcessMonitor() { + const config: tspm.IMonitorConfig = { + name: 'Project XYZ Monitor', + projectDir: '/path/to/your/project', + command: 'npm run xyz', + memoryLimitBytes: 500 * 1024 * 1024, // 500 MB memory limit + monitorIntervalMs: 5000, // Check memory usage every 5 seconds + logBufferSize: 200, // Keep last 200 log lines + }; -// Ensure that on process exit (e.g. Ctrl+C) we clean up the child process and prevent respawns. -process.on('SIGINT', () => { - console.log('Received SIGINT, stopping monitor...'); - monitor.stop(); - process.exit(); -}); \ No newline at end of file + const monitor = new tspm.ProcessMonitor(config); + monitor.start(); + + // Ensure that on process exit (e.g. Ctrl+C) we clean up the child process and prevent respawns. + process.on('SIGINT', () => { + console.log('Received SIGINT, stopping monitor...'); + monitor.stop(); + process.exit(); + }); + + // Get logs example + setTimeout(() => { + const logs = monitor.getLogs(10); // Get last 10 log lines + console.log('Latest logs:', logs); + }, 10000); +} + +// Example 2: Using Tspm (higher-level process manager) +async function exampleUsingTspm() { + const tspmInstance = new tspm.Tspm(); + + // Start a process + await tspmInstance.start({ + id: 'web-server', + name: 'Web Server', + projectDir: '/path/to/web/project', + command: 'npm run serve', + memoryLimitBytes: 300 * 1024 * 1024, // 300 MB + autorestart: true, + watch: true, + monitorIntervalMs: 10000, + }); + + // Start another process + await tspmInstance.start({ + id: 'api-server', + name: 'API Server', + projectDir: '/path/to/api/project', + command: 'npm run api', + memoryLimitBytes: 400 * 1024 * 1024, // 400 MB + autorestart: true, + }); + + // List all processes + const processes = tspmInstance.list(); + console.log('Running processes:', processes); + + // Get logs from a process + const logs = tspmInstance.getLogs('web-server', 20); + console.log('Web server logs:', logs); + + // Stop a process + await tspmInstance.stop('api-server'); + + // Handle graceful shutdown + process.on('SIGINT', async () => { + console.log('Shutting down all processes...'); + await tspmInstance.stopAll(); + process.exit(); + }); +} \ No newline at end of file diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index da40de4..244393a 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@git.zone/tspm', - version: '1.5.0', + version: '1.5.1', description: 'a no fuzz process manager' } diff --git a/ts/classes.processmonitor.ts b/ts/classes.processmonitor.ts index c4b719a..9ff427b 100644 --- a/ts/classes.processmonitor.ts +++ b/ts/classes.processmonitor.ts @@ -1,5 +1,6 @@ import * as plugins from './plugins.js'; import { ProcessWrapper, type IProcessLog } from './classes.processwrapper.js'; +import { Logger, ProcessError, handleError } from './utils.errorhandler.js'; export interface IMonitorConfig { name?: string; // Optional name to identify the instance @@ -18,9 +19,11 @@ export class ProcessMonitor { private intervalId: NodeJS.Timeout | null = null; private stopped: boolean = true; // Initially stopped until start() is called private restartCount: number = 0; + private logger: Logger; constructor(config: IMonitorConfig) { this.config = config; + this.logger = new Logger(`ProcessMonitor:${config.name || 'unnamed'}`); } public start(): void { @@ -31,7 +34,7 @@ export class ProcessMonitor { // Set the monitoring interval. const interval = this.config.monitorIntervalMs || 5000; - this.intervalId = setInterval(() => { + this.intervalId = setInterval((): void => { if (this.processWrapper && this.processWrapper.getPid()) { this.monitorProcessGroup(this.processWrapper.getPid()!, this.config.memoryLimitBytes); } @@ -40,7 +43,12 @@ export class ProcessMonitor { private spawnProcess(): void { // Don't spawn if the monitor has been stopped. - if (this.stopped) return; + if (this.stopped) { + this.logger.debug('Not spawning process because monitor is stopped'); + return; + } + + this.logger.info(`Spawning process: ${this.config.command}`); // Create a new process wrapper this.processWrapper = new ProcessWrapper({ @@ -53,7 +61,7 @@ export class ProcessMonitor { }); // Set up event handlers - this.processWrapper.on('log', (log) => { + this.processWrapper.on('log', (log: IProcessLog): void => { // Here we could add handlers to send logs somewhere // For now, we just log system messages to the console if (log.type === 'system') { @@ -61,26 +69,47 @@ export class ProcessMonitor { } }); - this.processWrapper.on('exit', (code, signal) => { - this.log(`Process exited with code ${code}, signal ${signal}.`); + this.processWrapper.on('exit', (code: number | null, signal: string | null): void => { + const exitMsg = `Process exited with code ${code}, signal ${signal}.`; + this.logger.info(exitMsg); + this.log(exitMsg); + if (!this.stopped) { + this.logger.info('Restarting process...'); this.log('Restarting process...'); this.restartCount++; this.spawnProcess(); + } else { + this.logger.debug('Not restarting process because monitor is stopped'); } }); - this.processWrapper.on('error', (error) => { - this.log(`Process error: ${error.message}`); + this.processWrapper.on('error', (error: Error | ProcessError): void => { + const errorMsg = error instanceof ProcessError + ? `Process error: ${error.toString()}` + : `Process error: ${error.message}`; + + this.logger.error(error); + this.log(errorMsg); + if (!this.stopped) { + this.logger.info('Restarting process due to error...'); this.log('Restarting process due to error...'); this.restartCount++; this.spawnProcess(); + } else { + this.logger.debug('Not restarting process because monitor is stopped'); } }); // Start the process - this.processWrapper.start(); + try { + this.processWrapper.start(); + } catch (error: Error | unknown) { + // The process wrapper will handle logging the error + // Just prevent it from bubbling up further + this.logger.error(`Failed to start process: ${error instanceof Error ? error.message : String(error)}`); + } } /** @@ -90,24 +119,40 @@ export class ProcessMonitor { private async monitorProcessGroup(pid: number, memoryLimit: number): Promise { try { const memoryUsage = await this.getProcessGroupMemory(pid); + + this.logger.debug( + `Memory usage for PID ${pid}: ${this.humanReadableBytes(memoryUsage)} (${memoryUsage} bytes)` + ); + + // Only log to the process log at longer intervals to avoid spamming this.log( `Current memory usage for process group (PID ${pid}): ${this.humanReadableBytes( memoryUsage )} (${memoryUsage} bytes)` ); + if (memoryUsage > memoryLimit) { - this.log( - `Memory usage ${this.humanReadableBytes( - memoryUsage - )} exceeds limit of ${this.humanReadableBytes(memoryLimit)}. Restarting process.` - ); + const memoryLimitMsg = `Memory usage ${this.humanReadableBytes( + memoryUsage + )} exceeds limit of ${this.humanReadableBytes(memoryLimit)}. Restarting process.`; + + this.logger.warn(memoryLimitMsg); + this.log(memoryLimitMsg); + // Stop the process wrapper, which will trigger the exit handler and restart if (this.processWrapper) { this.processWrapper.stop(); } } - } catch (error) { - this.log('Error monitoring process group: ' + error); + } catch (error: Error | unknown) { + const processError = new ProcessError( + error instanceof Error ? error.message : String(error), + 'ERR_MEMORY_MONITORING_FAILED', + { pid } + ); + + this.logger.error(processError); + this.log(`Error monitoring process group: ${processError.toString()}`); } } @@ -116,16 +161,40 @@ export class ProcessMonitor { */ private getProcessGroupMemory(pid: number): Promise { return new Promise((resolve, reject) => { - plugins.psTree(pid, (err, children) => { - if (err) return reject(err); + this.logger.debug(`Getting memory usage for process group with PID ${pid}`); + + plugins.psTree(pid, (err: Error | null, children: Array<{ PID: string }>) => { + if (err) { + const processError = new ProcessError( + `Failed to get process tree: ${err.message}`, + 'ERR_PSTREE_FAILED', + { pid } + ); + this.logger.debug(`psTree error: ${err.message}`); + return reject(processError); + } + // Include the main process and its children. const pids: number[] = [pid, ...children.map(child => Number(child.PID))]; - plugins.pidusage(pids, (err, stats) => { - if (err) return reject(err); + this.logger.debug(`Found ${pids.length} processes in group with parent PID ${pid}`); + + plugins.pidusage(pids, (err: Error | null, stats: Record) => { + if (err) { + const processError = new ProcessError( + `Failed to get process usage stats: ${err.message}`, + 'ERR_PIDUSAGE_FAILED', + { pids } + ); + this.logger.debug(`pidusage error: ${err.message}`); + return reject(processError); + } + let totalMemory = 0; for (const key in stats) { totalMemory += stats[key].memory; } + + this.logger.debug(`Total memory for process group: ${this.humanReadableBytes(totalMemory)}`); resolve(totalMemory); }); }); diff --git a/ts/classes.processwrapper.ts b/ts/classes.processwrapper.ts index 859d7d3..b9cb3c7 100644 --- a/ts/classes.processwrapper.ts +++ b/ts/classes.processwrapper.ts @@ -1,5 +1,6 @@ import * as plugins from './plugins.js'; import { EventEmitter } from 'events'; +import { Logger, ProcessError, handleError } from './utils.errorhandler.js'; export interface IProcessWrapperOptions { command: string; @@ -22,11 +23,13 @@ export class ProcessWrapper extends EventEmitter { private logs: IProcessLog[] = []; private logBufferSize: number; private startTime: Date | null = null; + private logger: Logger; constructor(options: IProcessWrapperOptions) { super(); this.options = options; this.logBufferSize = options.logBuffer || 100; + this.logger = new Logger(`ProcessWrapper:${options.name}`); } /** @@ -36,6 +39,8 @@ export class ProcessWrapper extends EventEmitter { this.addSystemLog('Starting process...'); try { + this.logger.debug(`Starting process: ${this.options.command}`); + if (this.options.args && this.options.args.length > 0) { this.process = plugins.childProcess.spawn(this.options.command, this.options.args, { cwd: this.options.cwd, @@ -56,14 +61,22 @@ export class ProcessWrapper extends EventEmitter { // Handle process exit this.process.on('exit', (code, signal) => { - this.addSystemLog(`Process exited with code ${code}, signal ${signal}`); + const exitMessage = `Process exited with code ${code}, signal ${signal}`; + this.logger.info(exitMessage); + this.addSystemLog(exitMessage); this.emit('exit', code, signal); }); // Handle errors this.process.on('error', (error) => { - this.addSystemLog(`Process error: ${error.message}`); - this.emit('error', error); + const processError = new ProcessError( + error.message, + 'ERR_PROCESS_EXECUTION', + { command: this.options.command, pid: this.process?.pid } + ); + this.logger.error(processError); + this.addSystemLog(`Process error: ${processError.toString()}`); + this.emit('error', processError); }); // Capture stdout @@ -91,12 +104,22 @@ export class ProcessWrapper extends EventEmitter { } this.addSystemLog(`Process started with PID ${this.process.pid}`); + this.logger.info(`Process started with PID ${this.process.pid}`); this.emit('start', this.process.pid); - } catch (error) { - this.addSystemLog(`Failed to start process: ${error.message}`); - this.emit('error', error); - throw error; + } catch (error: Error | unknown) { + const processError = error instanceof ProcessError + ? error + : new ProcessError( + error instanceof Error ? error.message : String(error), + 'ERR_PROCESS_START_FAILED', + { command: this.options.command } + ); + + this.logger.error(processError); + this.addSystemLog(`Failed to start process: ${processError.toString()}`); + this.emit('error', processError); + throw processError; } } @@ -105,30 +128,43 @@ export class ProcessWrapper extends EventEmitter { */ public stop(): void { if (!this.process) { + this.logger.debug('Stop called but no process is running'); this.addSystemLog('No process running'); return; } + this.logger.info('Stopping process...'); this.addSystemLog('Stopping process...'); // First try SIGTERM for graceful shutdown if (this.process.pid) { try { + this.logger.debug(`Sending SIGTERM to process ${this.process.pid}`); process.kill(this.process.pid, 'SIGTERM'); // Give it 5 seconds to shut down gracefully - setTimeout(() => { + setTimeout((): void => { if (this.process && this.process.pid) { + this.logger.warn(`Process ${this.process.pid} did not exit gracefully, force killing...`); this.addSystemLog('Process did not exit gracefully, force killing...'); try { process.kill(this.process.pid, 'SIGKILL'); - } catch (error) { + } catch (error: Error | unknown) { // Process might have exited between checks + this.logger.debug(`Failed to send SIGKILL, process probably already exited: ${ + error instanceof Error ? error.message : String(error) + }`); } } }, 5000); - } catch (error) { - this.addSystemLog(`Error stopping process: ${error.message}`); + } catch (error: Error | unknown) { + const processError = new ProcessError( + error instanceof Error ? error.message : String(error), + 'ERR_PROCESS_STOP_FAILED', + { pid: this.process.pid } + ); + this.logger.error(processError); + this.addSystemLog(`Error stopping process: ${processError.toString()}`); } } } diff --git a/ts/classes.tspm.ts b/ts/classes.tspm.ts index 82fb275..9c7343f 100644 --- a/ts/classes.tspm.ts +++ b/ts/classes.tspm.ts @@ -2,6 +2,13 @@ import * as plugins from './plugins.js'; import * as paths from './paths.js'; import { ProcessMonitor, type IMonitorConfig } from './classes.processmonitor.js'; import { TspmConfig } from './classes.config.js'; +import { + Logger, + ProcessError, + ConfigError, + ValidationError, + handleError +} from './utils.errorhandler.js'; export interface IProcessConfig extends IMonitorConfig { id: string; // Unique identifier for the process @@ -32,8 +39,10 @@ export class Tspm { private processInfo: Map = new Map(); private config: TspmConfig; private configStorageKey = 'processes'; + private logger: Logger; constructor() { + this.logger = new Logger('Tspm'); this.config = new TspmConfig(); this.loadProcessConfigs(); } @@ -42,53 +51,113 @@ export class Tspm { * Start a new process with the given configuration */ public async start(config: IProcessConfig): Promise { - // Check if process with this id already exists - if (this.processes.has(config.id)) { - throw new Error(`Process with id '${config.id}' already exists`); + this.logger.info(`Starting process with id '${config.id}'`); + + // Validate config + if (!config.id || !config.command || !config.projectDir) { + throw new ValidationError( + 'Invalid process configuration: missing required fields', + 'ERR_INVALID_CONFIG', + { config } + ); } - // Create and store process config - this.processConfigs.set(config.id, config); + // Check if process with this id already exists + if (this.processes.has(config.id)) { + throw new ValidationError( + `Process with id '${config.id}' already exists`, + 'ERR_DUPLICATE_PROCESS' + ); + } - // Initialize process info - this.processInfo.set(config.id, { - id: config.id, - status: 'stopped', - memory: 0, - restarts: 0 - }); - - // Create and start process monitor - const monitor = new ProcessMonitor({ - name: config.name || config.id, - projectDir: config.projectDir, - command: config.command, - args: config.args, - memoryLimitBytes: config.memoryLimitBytes, - monitorIntervalMs: config.monitorIntervalMs - }); - - this.processes.set(config.id, monitor); - monitor.start(); - - // Update process info - this.updateProcessInfo(config.id, { status: 'online' }); - - // Save updated configs - await this.saveProcessConfigs(); + try { + // Create and store process config + this.processConfigs.set(config.id, config); + + // Initialize process info + this.processInfo.set(config.id, { + id: config.id, + status: 'stopped', + memory: 0, + restarts: 0 + }); + + // Create and start process monitor + const monitor = new ProcessMonitor({ + name: config.name || config.id, + projectDir: config.projectDir, + command: config.command, + args: config.args, + memoryLimitBytes: config.memoryLimitBytes, + monitorIntervalMs: config.monitorIntervalMs, + env: config.env, + logBufferSize: config.logBufferSize + }); + + this.processes.set(config.id, monitor); + monitor.start(); + + // Update process info + this.updateProcessInfo(config.id, { status: 'online' }); + + // Save updated configs + await this.saveProcessConfigs(); + + this.logger.info(`Successfully started process with id '${config.id}'`); + } catch (error: Error | unknown) { + // Clean up in case of error + this.processConfigs.delete(config.id); + this.processInfo.delete(config.id); + this.processes.delete(config.id); + + if (error instanceof Error) { + this.logger.error(error); + throw new ProcessError( + `Failed to start process: ${error.message}`, + 'ERR_PROCESS_START_FAILED', + { id: config.id, command: config.command } + ); + } else { + const genericError = new ProcessError( + `Failed to start process: ${String(error)}`, + 'ERR_PROCESS_START_FAILED', + { id: config.id } + ); + this.logger.error(genericError); + throw genericError; + } + } } /** * Stop a process by id */ public async stop(id: string): Promise { + this.logger.info(`Stopping process with id '${id}'`); + const monitor = this.processes.get(id); if (!monitor) { - throw new Error(`Process with id '${id}' not found`); + const error = new ValidationError( + `Process with id '${id}' not found`, + 'ERR_PROCESS_NOT_FOUND' + ); + this.logger.error(error); + throw error; } - monitor.stop(); - this.updateProcessInfo(id, { status: 'stopped' }); + try { + monitor.stop(); + this.updateProcessInfo(id, { status: 'stopped' }); + this.logger.info(`Successfully stopped process with id '${id}'`); + } catch (error: Error | unknown) { + const processError = new ProcessError( + `Failed to stop process: ${error instanceof Error ? error.message : String(error)}`, + 'ERR_PROCESS_STOP_FAILED', + { id } + ); + this.logger.error(processError); + throw processError; + } // Don't remove from the maps, just mark as stopped // This allows it to be restarted later @@ -98,36 +167,57 @@ export class Tspm { * Restart a process by id */ public async restart(id: string): Promise { + this.logger.info(`Restarting process with id '${id}'`); + const monitor = this.processes.get(id); const config = this.processConfigs.get(id); if (!monitor || !config) { - throw new Error(`Process with id '${id}' not found`); + const error = new ValidationError( + `Process with id '${id}' not found`, + 'ERR_PROCESS_NOT_FOUND' + ); + this.logger.error(error); + throw error; } - // Stop and then start the process - monitor.stop(); - - // Create a new monitor instance - const newMonitor = new ProcessMonitor({ - name: config.name || config.id, - projectDir: config.projectDir, - command: config.command, - args: config.args, - memoryLimitBytes: config.memoryLimitBytes, - monitorIntervalMs: config.monitorIntervalMs - }); - - this.processes.set(id, newMonitor); - newMonitor.start(); - - // Update restart count - const info = this.processInfo.get(id); - if (info) { - this.updateProcessInfo(id, { - status: 'online', - restarts: info.restarts + 1 + try { + // Stop and then start the process + monitor.stop(); + + // Create a new monitor instance + const newMonitor = new ProcessMonitor({ + name: config.name || config.id, + projectDir: config.projectDir, + command: config.command, + args: config.args, + memoryLimitBytes: config.memoryLimitBytes, + monitorIntervalMs: config.monitorIntervalMs, + env: config.env, + logBufferSize: config.logBufferSize }); + + this.processes.set(id, newMonitor); + newMonitor.start(); + + // Update restart count + const info = this.processInfo.get(id); + if (info) { + this.updateProcessInfo(id, { + status: 'online', + restarts: info.restarts + 1 + }); + } + + this.logger.info(`Successfully restarted process with id '${id}'`); + } catch (error: Error | unknown) { + const processError = new ProcessError( + `Failed to restart process: ${error instanceof Error ? error.message : String(error)}`, + 'ERR_PROCESS_RESTART_FAILED', + { id } + ); + this.logger.error(processError); + throw processError; } } @@ -135,20 +225,52 @@ export class Tspm { * Delete a process by id */ public async delete(id: string): Promise { - // Stop the process if it's running - try { - await this.stop(id); - } catch (error) { - // Ignore errors if the process is not running + this.logger.info(`Deleting process with id '${id}'`); + + // Check if process exists + if (!this.processConfigs.has(id)) { + const error = new ValidationError( + `Process with id '${id}' not found`, + 'ERR_PROCESS_NOT_FOUND' + ); + this.logger.error(error); + throw error; } - // Remove from all maps - this.processes.delete(id); - this.processConfigs.delete(id); - this.processInfo.delete(id); - - // Save updated configs - await this.saveProcessConfigs(); + // Stop the process if it's running + try { + if (this.processes.has(id)) { + await this.stop(id); + } + + // Remove from all maps + this.processes.delete(id); + this.processConfigs.delete(id); + this.processInfo.delete(id); + + // Save updated configs + await this.saveProcessConfigs(); + + this.logger.info(`Successfully deleted process with id '${id}'`); + } catch (error: Error | unknown) { + // Even if stop fails, we should still try to delete the configuration + try { + this.processes.delete(id); + this.processConfigs.delete(id); + this.processInfo.delete(id); + await this.saveProcessConfigs(); + + this.logger.info(`Successfully deleted process with id '${id}' after stopping failure`); + } catch (deleteError: Error | unknown) { + const configError = new ConfigError( + `Failed to delete process configuration: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`, + 'ERR_CONFIG_DELETE_FAILED', + { id } + ); + this.logger.error(configError); + throw configError; + } + } } /** @@ -227,33 +349,71 @@ export class Tspm { * Save all process configurations to config storage */ private async saveProcessConfigs(): Promise { - const configs = Array.from(this.processConfigs.values()); - await this.config.writeKey(this.configStorageKey, JSON.stringify(configs)); + this.logger.debug('Saving process configurations to storage'); + + try { + const configs = Array.from(this.processConfigs.values()); + await this.config.writeKey(this.configStorageKey, JSON.stringify(configs)); + this.logger.debug(`Saved ${configs.length} process configurations`); + } catch (error: Error | unknown) { + const configError = new ConfigError( + `Failed to save process configurations: ${error instanceof Error ? error.message : String(error)}`, + 'ERR_CONFIG_SAVE_FAILED' + ); + this.logger.error(configError); + throw configError; + } } /** * Load process configurations from config storage */ private async loadProcessConfigs(): Promise { + this.logger.debug('Loading process configurations from storage'); + try { const configsJson = await this.config.readKey(this.configStorageKey); if (configsJson) { - const configs = JSON.parse(configsJson) as IProcessConfig[]; - for (const config of configs) { - this.processConfigs.set(config.id, config); + try { + const configs = JSON.parse(configsJson) as IProcessConfig[]; + this.logger.debug(`Loaded ${configs.length} process configurations`); - // Initialize process info - this.processInfo.set(config.id, { - id: config.id, - status: 'stopped', - memory: 0, - restarts: 0 - }); + for (const config of configs) { + // Validate config + if (!config.id || !config.command || !config.projectDir) { + this.logger.warn(`Skipping invalid process config for id '${config.id || 'unknown'}'`); + continue; + } + + this.processConfigs.set(config.id, config); + + // Initialize process info + this.processInfo.set(config.id, { + id: config.id, + status: 'stopped', + memory: 0, + restarts: 0 + }); + } + } catch (parseError: Error | unknown) { + const configError = new ConfigError( + `Failed to parse process configurations: ${parseError instanceof Error ? parseError.message : String(parseError)}`, + 'ERR_CONFIG_PARSE_FAILED' + ); + this.logger.error(configError); + throw configError; } + } else { + this.logger.info('No saved process configurations found'); } - } catch (error) { + } catch (error: Error | unknown) { + // Only throw if it's not the "no configs found" case + if (error instanceof ConfigError) { + throw error; + } + // If no configs found or error reading, just continue with empty configs - console.log('No saved process configurations found'); + this.logger.info('No saved process configurations found or error reading them'); } } } \ No newline at end of file diff --git a/ts/cli.ts b/ts/cli.ts index 58db4af..cb95124 100644 --- a/ts/cli.ts +++ b/ts/cli.ts @@ -1,17 +1,40 @@ import * as plugins from './plugins.js'; import * as paths from './paths.js'; -import { Tspm, IProcessConfig } from './classes.tspm.js'; +import { Tspm, type IProcessConfig } from './classes.tspm.js'; +import { + Logger, + LogLevel, + handleError, + TspmError, + ProcessError, + ConfigError, + ValidationError +} from './utils.errorhandler.js'; -export const run = async () => { +// Define interface for CLI arguments +interface CliArguments { + _: (string | number)[]; + [key: string]: any; +} + +export const run = async (): Promise => { + const cliLogger = new Logger('CLI'); const tspmProjectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir); const tspm = new Tspm(); + // Check if debug mode is enabled + const debugMode = process.env.TSPM_DEBUG === 'true'; + if (debugMode) { + cliLogger.setLevel(LogLevel.DEBUG); + cliLogger.debug('Debug mode enabled'); + } + const smartcliInstance = new plugins.smartcli.Smartcli(); smartcliInstance.addVersion(tspmProjectinfo.npm.version); // Default command - show help and list processes smartcliInstance.standardCommand().subscribe({ - next: async (argvArg) => { + next: async (argvArg: CliArguments) => { console.log(`TSPM - TypeScript Process Manager v${tspmProjectinfo.npm.version}`); console.log('Usage: tspm [command] [options]'); console.log('\nCommands:'); @@ -46,7 +69,7 @@ export const run = async () => { // Start command - start a new process smartcliInstance.addCommand('start').subscribe({ - next: async (argvArg) => { + next: async (argvArg: CliArguments) => { const script = argvArg._.length > 1 ? String(argvArg._[1]) : ''; if (!script) { console.error('Error: Missing script argument. Usage: tspm start