diff --git a/changelog.md b/changelog.md index 8c610ac..3a7a24f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2026-03-27 - 3.6.3 - fix(tapbundle_serverside) +add TapNodeTools cleanup hooks to stop SmartNetwork processes after tests + +- replace the exported tapNodeTools singleton with a TapNodeTools class that registers cleanup on the tap instance +- run registered cleanup functions at the end of tap.start() to prevent lingering background processes from keeping Node.js alive +- stop SmartNetwork after selecting Chromium runtime ports and update smartnetwork to ^4.5.2 + ## 2026-03-27 - 3.6.2 - fix(cli,chromium-runtime) clean up long-lived test runner resources after runs to prevent hanging processes diff --git a/package.json b/package.json index d0e071e..3d011a8 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "@push.rocks/smartjson": "^6.0.0", "@push.rocks/smartlog": "^3.2.1", "@push.rocks/smartmongo": "^5.1.0", - "@push.rocks/smartnetwork": "^4.4.0", + "@push.rocks/smartnetwork": "^4.5.2", "@push.rocks/smartpath": "^6.0.0", "@push.rocks/smartpromise": "^4.2.3", "@push.rocks/smartrequest": "^5.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5d477f4..65b6dc3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,8 +51,8 @@ importers: specifier: ^5.1.0 version: 5.1.0(socks@2.8.7) '@push.rocks/smartnetwork': - specifier: ^4.4.0 - version: 4.4.0 + specifier: ^4.5.2 + version: 4.5.2 '@push.rocks/smartpath': specifier: ^6.0.0 version: 6.0.0 @@ -661,89 +661,105 @@ packages: resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-wasm32@0.34.5': resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} @@ -948,9 +964,6 @@ packages: resolution: {integrity: sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==} engines: {node: '>=18'} - '@leichtgewicht/ip-codec@2.0.5': - resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} - '@lit-labs/ssr-dom-shim@1.4.0': resolution: {integrity: sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==} @@ -1104,8 +1117,8 @@ packages: '@push.rocks/smartdelay@3.0.5': resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==} - '@push.rocks/smartdns@7.6.1': - resolution: {integrity: sha512-nnP5+A2GOt0WsHrYhtKERmjdEHUchc+QbCCBEqlyeQTn+mNfx2WZvKVI1DFRJt8lamvzxP6Hr/BSe3WHdh4Snw==} + '@push.rocks/smartdns@7.9.0': + resolution: {integrity: sha512-1nDUfyXQo6j9HTUfcjE+BLeAv9QZ7WtAsM1V28zIoFdUpjNg/5g382L024H73PHsxh6lSYNhYYmFvWqzFQhXKg==} '@push.rocks/smartenv@5.0.13': resolution: {integrity: sha512-ACXmUcHZHl2CF2jnVuRw9saRRrZvJblCRs2d+K5aLR1DfkYFX3eA21kcMlKeLisI3aGNbIj9vz/rowN5qkRkfA==} @@ -1179,8 +1192,8 @@ packages: '@push.rocks/smartmongo@5.1.0': resolution: {integrity: sha512-2tpKf8K+SMdLHOEpafgKPIN+ypWTLwHc33hCUDNMQ1KaL7vokkavA44+fHxQydOGPMtDi22tSMFeVMCcUSzs4w==} - '@push.rocks/smartnetwork@4.4.0': - resolution: {integrity: sha512-OvFtz41cvQ7lcXwaIOhghNUUlNoMxvwKDctbDvMyuZyEH08SpLjhyv2FuKbKL/mgwA/WxakTbohoC8SW7t+kiw==} + '@push.rocks/smartnetwork@4.5.2': + resolution: {integrity: sha512-lbMMyc2f/WWd5+qzZyF1ynXndjCtasxPWmj/d8GUuis9rDrW7sLIT1PlAPC2F6Qsy4H/K32JrYU+01d/6sWObg==} '@push.rocks/smartnpm@2.0.6': resolution: {integrity: sha512-7anKDOjX6gXWs1IAc+YWz9ZZ8gDsTwaLh+CxRnGHjAawOmK788NrrgVCg2Fb3qojrPnoxecc46F8Ivp1BT7Izw==} @@ -1197,9 +1210,6 @@ packages: '@push.rocks/smartpdf@4.2.0': resolution: {integrity: sha512-+egzby5QKJGO10MDvWp+N69cJ8i5M354l9ntc+uLRpxuq/FEY9kigpRwMvRYF5qwOBTuGTLqvmvILzlLtboAQg==} - '@push.rocks/smartping@1.0.8': - resolution: {integrity: sha512-Fvx1Db6hSsDOI6pdiCuS9GjtOX8ugx865YQrPg5vK2iw6Qj/srwyXcWLFYt+19WVKtvtWDJIAKbW+q3bXFsCeA==} - '@push.rocks/smartpromise@4.2.3': resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==} @@ -1325,36 +1335,42 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.0-rc.11': resolution: {integrity: sha512-jfndI9tsfm4APzjNt6QdBkYwre5lRPUgHeDHoI7ydKUuJvz3lZeCfMsI56BZj+7BYqiKsJm7cfd/6KYV7ubrBg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.11': resolution: {integrity: sha512-ZlFgw46NOAGMgcdvdYwAGu2Q+SLFA9LzbJLW+iyMOJyhj5wk6P3KEE9Gct4xWwSzFoPI7JCdYmYMzVtlgQ+zfw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.11': resolution: {integrity: sha512-hIOYmuT6ofM4K04XAZd3OzMySEO4K0/nc9+jmNcxNAxRi6c5UWpqfw3KMFV4MVFWL+jQsSh+bGw2VqmaPMTLyw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.0.0-rc.11': resolution: {integrity: sha512-qXBQQO9OvkjjQPLdUVr7Nr2t3QTZI7s4KZtfw7HzBgjbmAPSFwSv4rmET9lLSgq3rH/ndA3ngv3Qb8l2njoPNA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.0-rc.11': resolution: {integrity: sha512-/tpFfoSTzUkH9LPY+cYbqZBDyyX62w5fICq9qzsHLL8uTI6BHip3Q9Uzft0wylk/i8OOwKik8OxW+QAhDmzwmg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@rolldown/binding-openharmony-arm64@1.0.0-rc.11': resolution: {integrity: sha512-mcp3Rio2w72IvdZG0oQ4bM2c2oumtwHfUfKncUM6zGgz0KgPz4YmDPQfnXEiY5t3+KD/i8HG2rOB/LxdmieK2g==} @@ -1396,21 +1412,25 @@ packages: resolution: {integrity: sha512-Z4reus7UxGM4+JuhiIht8KuGP1KgM7nNhOlXUHcQCMswP/Rymj5oJQN3TDWgijFUZs09ULl8t3T+AQAVTd/WvA==} cpu: [arm64] os: [linux] + libc: [glibc] '@rspack/binding-linux-arm64-musl@1.7.10': resolution: {integrity: sha512-LYaoVmWizG4oQ3g+St3eM5qxsyfH07kLirP7NJcDMgvu3eQ29MeyTZ3ugkgW6LvlmJue7eTQyf6CZlanoF5SSg==} cpu: [arm64] os: [linux] + libc: [musl] '@rspack/binding-linux-x64-gnu@1.7.10': resolution: {integrity: sha512-aIm2G4Kcm3qxDTNqKarK0oaLY2iXnCmpRQQhAcMlR0aS2LmxL89XzVeRr9GFA1MzGrAsZONWCLkxQvn3WUbm4Q==} cpu: [x64] os: [linux] + libc: [glibc] '@rspack/binding-linux-x64-musl@1.7.10': resolution: {integrity: sha512-SIHQbAgB9IPH0H3H+i5rN5jo9yA/yTMq8b7XfRkTMvZ7P7MXxJ0dE8EJu3BmCLM19sqnTc2eX+SVfE8ZMDzghA==} cpu: [x64] os: [linux] + libc: [musl] '@rspack/binding-wasm32-wasi@1.7.10': resolution: {integrity: sha512-J9HDXHD1tj+9FmX4+K3CTkO7dCE2bootlR37YuC2Owc0Lwl1/i2oGT71KHnMqI9faF/hipAaQM5OywkiiuNB7w==} @@ -1712,21 +1732,12 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - '@types/bn.js@5.2.0': - resolution: {integrity: sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q==} - '@types/clean-css@4.2.11': resolution: {integrity: sha512-Y8n81lQVTAfP2TOdtJJEsCoYl1AnOkqDqMvXb9/7pfgZZ7r8YrEyurrAvAoAjHOGXKRybay+5CsExqIH6liccw==} '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - '@types/dns-packet@5.6.5': - resolution: {integrity: sha512-qXOC7XLOEe43ehtWJCMnQXvgcIpv6rPmQ1jXT98Ad8A3TB1Ue50jsCbSSSyuazScEuZ/Q026vHbrOTVkmwA+7Q==} - - '@types/elliptic@6.4.18': - resolution: {integrity: sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw==} - '@types/fs-extra@11.0.4': resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} @@ -1775,9 +1786,6 @@ packages: '@types/node@25.5.0': resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} - '@types/ping@0.4.4': - resolution: {integrity: sha512-ifvo6w2f5eJYlXm+HiVx67iJe8WZp87sfa683nlqED5Vnt9Z93onkokNoWqOG21EaE8fMxyKPobE+mkPEyxsdw==} - '@types/relateurl@0.2.33': resolution: {integrity: sha512-bTQCKsVbIdzLqZhLkF5fcJQreE4y1ro4DIyVrlDNSCJRRwHhB8Z+4zXXa8jN6eDvc2HbRsEYgbvrnGvi54EpSw==} @@ -1913,6 +1921,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + bare-events@2.8.2: resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} peerDependencies: @@ -1961,9 +1973,6 @@ packages: bmp-ts@1.0.9: resolution: {integrity: sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==} - bn.js@4.12.2: - resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==} - bowser@2.12.1: resolution: {integrity: sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==} @@ -1973,12 +1982,13 @@ packages: brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + engines: {node: 18 || 20 || >=22} + broadcast-channel@7.2.0: resolution: {integrity: sha512-JgraikEriG/TxBUi2W/w2O0jhHjXZUtXAvCZH0Yr3whjxYVgAg0hSe6r/teM+I5H5Q/q6RhyuKdC2pHNlFyepQ==} - brorand@1.1.0: - resolution: {integrity: sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=} - bson@6.10.4: resolution: {integrity: sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==} engines: {node: '>=16.20.1'} @@ -2163,10 +2173,6 @@ packages: devtools-protocol@0.0.1581282: resolution: {integrity: sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ==} - dns-packet@5.6.1: - resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} - engines: {node: '>=6'} - dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -2174,9 +2180,6 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - elliptic@6.6.1: - resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2439,9 +2442,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} - hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -2459,9 +2459,6 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - hmac-drbg@1.0.1: - resolution: {integrity: sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=} - html-minifier@4.0.0: resolution: {integrity: sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==} engines: {node: '>=6'} @@ -2557,9 +2554,6 @@ packages: resolution: {integrity: sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==} engines: {node: '>=20'} - isopen@1.3.0: - resolution: {integrity: sha512-AN6Q9J0UlqHFl1fN/2xJCHCBLCBCFDjZhpGBO1gh3wzgRPsFSFBUL36I2Lbfd9qkuoj58axmE7j83iejTQsk8Q==} - jackspeak@4.1.1: resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} engines: {node: 20 || >=22} @@ -2652,6 +2646,10 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + maxmind@5.0.5: + resolution: {integrity: sha512-1lcH2kMjbBpCFhuHaMU32vz8CuOsKttRcWMQyXvtlklopCzN7NNHSVR/h9RYa8JPuFTGmkn2vYARm+7cIGuqDw==} + engines: {node: '>=12', npm: '>=6'} + mdast-util-find-and-replace@3.0.2: resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} @@ -2810,16 +2808,14 @@ packages: mingo@7.2.0: resolution: {integrity: sha512-UeX942qZpofn5L97h295SkS7j/ADf7Qac8gdRCMBPxi0/1m70aeB2owLFvWbyuMj1dowonlivlVRQVDx+6h+7Q==} - minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - - minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=} - minimatch@10.1.1: resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} engines: {node: 20 || >=22} + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -2837,6 +2833,10 @@ packages: mitt@3.0.1: resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + mmdb-lib@3.0.2: + resolution: {integrity: sha512-7e87vk0DdWT647wjcfEtWeMtjm+zVGqNohN/aeIymbUfjHQ2T4Sx5kM+1irVDBSloNC3CkGKxswdMoo8yhqTDg==} + engines: {node: '>=10', npm: '>=6'} + mongodb-connection-string-url@3.0.2: resolution: {integrity: sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==} @@ -3043,10 +3043,6 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} - ping@0.4.4: - resolution: {integrity: sha512-56ZMC0j7SCsMMLdOoUg12VZCfj/+ZO+yfOSjaNCRrmZZr6GLbN2X/Ui56T15dI8NhiHckaw5X2pvyfAomanwqQ==} - engines: {node: '>=4.0.0'} - pixelmatch@5.3.0: resolution: {integrity: sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==} hasBin: true @@ -3324,12 +3320,6 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - systeminformation@5.27.11: - resolution: {integrity: sha512-K3Lto/2m3K2twmKHdgx5B+0in9qhXK4YnoT9rIlgwN/4v7OV5c8IjbeAUkuky/6VzCQC7iKCAqi8rZathCdjHg==} - engines: {node: '>=8.0.0'} - os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android] - hasBin: true - tagged-tag@1.0.0: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} @@ -3355,6 +3345,10 @@ packages: through@2.3.8: resolution: {integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=} + tiny-lru@11.4.7: + resolution: {integrity: sha512-w/Te7uMUVeH0CR8vZIjr+XiN41V+30lkDdK+NRIDCUYKKuL9VcmaUEmaPISuwGhLlrTGh5yu18lENtR9axSxYw==} + engines: {node: '>=12'} + tiny-worker@2.3.0: resolution: {integrity: sha512-pJ70wq5EAqTAEl9IkGzA+fN0836rycEuz2Cn6yeZ6FRzlVS5IDOkFHpIoEsksPRQV34GDqXm65+OlnZqUSyK2g==} @@ -4784,8 +4778,6 @@ snapshots: '@jimp/types': 1.6.0 tinycolor2: 1.6.0 - '@leichtgewicht/ip-codec@2.0.5': {} - '@lit-labs/ssr-dom-shim@1.4.0': {} '@lit/reactive-element@2.1.1': @@ -5185,19 +5177,15 @@ snapshots: dependencies: '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartdns@7.6.1': + '@push.rocks/smartdns@7.9.0': dependencies: '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartenv': 5.0.13 + '@push.rocks/smartenv': 6.0.0 '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartrequest': 2.1.0 - '@tsclass/tsclass': 9.4.0 - '@types/dns-packet': 5.6.5 - '@types/elliptic': 6.4.18 + '@push.rocks/smartrust': 1.3.2 + '@tsclass/tsclass': 9.5.0 acme-client: 5.4.0 - dns-packet: 5.6.1 - elliptic: 6.6.1 - minimatch: 10.1.1 + minimatch: 10.2.4 transitivePeerDependencies: - supports-color @@ -5423,14 +5411,11 @@ snapshots: - supports-color - vue - '@push.rocks/smartnetwork@4.4.0': + '@push.rocks/smartnetwork@4.5.2': dependencies: - '@push.rocks/smartdns': 7.6.1 - '@push.rocks/smartping': 1.0.8 - '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartstring': 4.1.0 - isopen: 1.3.0 - systeminformation: 5.27.11 + '@push.rocks/smartdns': 7.9.0 + '@push.rocks/smartrust': 1.3.2 + maxmind: 5.0.5 transitivePeerDependencies: - supports-color @@ -5471,7 +5456,7 @@ snapshots: '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartfs': 1.5.0 '@push.rocks/smartjimp': 1.2.0 - '@push.rocks/smartnetwork': 4.4.0 + '@push.rocks/smartnetwork': 4.5.2 '@push.rocks/smartpath': 6.0.0 '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartpuppeteer': 2.0.5(typescript@6.0.2) @@ -5493,11 +5478,6 @@ snapshots: - utf-8-validate - vue - '@push.rocks/smartping@1.0.8': - dependencies: - '@types/ping': 0.4.4 - ping: 0.4.4 - '@push.rocks/smartpromise@4.2.3': {} '@push.rocks/smartpuppeteer@2.0.5(typescript@6.0.2)': @@ -6189,10 +6169,6 @@ snapshots: tslib: 2.8.1 optional: true - '@types/bn.js@5.2.0': - dependencies: - '@types/node': 25.5.0 - '@types/clean-css@4.2.11': dependencies: '@types/node': 25.5.0 @@ -6202,14 +6178,6 @@ snapshots: dependencies: '@types/ms': 2.1.0 - '@types/dns-packet@5.6.5': - dependencies: - '@types/node': 25.5.0 - - '@types/elliptic@6.4.18': - dependencies: - '@types/bn.js': 5.2.0 - '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 @@ -6263,8 +6231,6 @@ snapshots: dependencies: undici-types: 7.18.2 - '@types/ping@0.4.4': {} - '@types/relateurl@0.2.33': {} '@types/semver@7.7.1': {} @@ -6388,6 +6354,8 @@ snapshots: balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + bare-events@2.8.2: {} bare-fs@4.5.5: @@ -6427,8 +6395,6 @@ snapshots: bmp-ts@1.0.9: {} - bn.js@4.12.2: {} - bowser@2.12.1: {} brace-expansion@1.1.12: @@ -6440,6 +6406,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.5: + dependencies: + balanced-match: 4.0.4 + broadcast-channel@7.2.0: dependencies: '@babel/runtime': 7.28.4 @@ -6447,8 +6417,6 @@ snapshots: p-queue: 6.6.2 unload: 2.4.1 - brorand@1.1.0: {} - bson@6.10.4: {} buffer-crc32@0.2.13: {} @@ -6617,10 +6585,6 @@ snapshots: devtools-protocol@0.0.1581282: {} - dns-packet@5.6.1: - dependencies: - '@leichtgewicht/ip-codec': 2.0.5 - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -6629,16 +6593,6 @@ snapshots: eastasianwidth@0.2.0: {} - elliptic@6.6.1: - dependencies: - bn.js: 4.12.2 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -6972,11 +6926,6 @@ snapshots: dependencies: has-symbols: 1.1.0 - hash.js@1.1.7: - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -7007,12 +6956,6 @@ snapshots: he@1.2.0: {} - hmac-drbg@1.0.1: - dependencies: - hash.js: 1.1.7 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - html-minifier@4.0.0: dependencies: camel-case: 3.0.0 @@ -7110,8 +7053,6 @@ snapshots: isexe@4.0.0: {} - isopen@1.3.0: {} - jackspeak@4.1.1: dependencies: '@isaacs/cliui': 8.0.2 @@ -7225,6 +7166,11 @@ snapshots: math-intrinsics@1.1.0: {} + maxmind@5.0.5: + dependencies: + mmdb-lib: 3.0.2 + tiny-lru: 11.4.7 + mdast-util-find-and-replace@3.0.2: dependencies: '@types/mdast': 4.0.4 @@ -7566,14 +7512,14 @@ snapshots: mingo@7.2.0: {} - minimalistic-assert@1.0.1: {} - - minimalistic-crypto-utils@1.0.1: {} - minimatch@10.1.1: dependencies: '@isaacs/brace-expansion': 5.0.0 + minimatch@10.2.4: + dependencies: + brace-expansion: 5.0.5 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 @@ -7588,6 +7534,8 @@ snapshots: mitt@3.0.1: {} + mmdb-lib@3.0.2: {} + mongodb-connection-string-url@3.0.2: dependencies: '@types/whatwg-url': 11.0.5 @@ -7791,8 +7739,6 @@ snapshots: picomatch@4.0.3: {} - ping@0.4.4: {} - pixelmatch@5.3.0: dependencies: pngjs: 6.0.0 @@ -8162,8 +8108,6 @@ snapshots: symbol-tree@3.2.4: {} - systeminformation@5.27.11: {} - tagged-tag@1.0.0: {} tar-fs@3.1.2: @@ -8219,6 +8163,8 @@ snapshots: through@2.3.8: {} + tiny-lru@11.4.7: {} + tiny-worker@2.3.0: dependencies: esm: 3.2.25 diff --git a/test/tapbundle/test.network-tools.node.ts b/test/tapbundle/test.network-tools.node.ts index c60934a..fbb6376 100644 --- a/test/tapbundle/test.network-tools.node.ts +++ b/test/tapbundle/test.network-tools.node.ts @@ -1,5 +1,7 @@ import { tap, expect } from '../../ts_tapbundle/index.js'; -import { tapNodeTools } from '../../ts_tapbundle_serverside/index.js'; +import { TapNodeTools } from '../../ts_tapbundle_serverside/index.js'; + +const tapNodeTools = new TapNodeTools(tap); tap.test('should find a single free port', async () => { const port = await tapNodeTools.findFreePort(); diff --git a/test/tapbundle/test.node.ts b/test/tapbundle/test.node.ts index 5ab03a4..174801b 100644 --- a/test/tapbundle/test.node.ts +++ b/test/tapbundle/test.node.ts @@ -1,6 +1,7 @@ import { tap, expect } from '../../ts_tapbundle/index.js'; +import { TapNodeTools } from '../../ts_tapbundle_serverside/index.js'; -import { tapNodeTools } from '../../ts_tapbundle_serverside/index.js'; +const tapNodeTools = new TapNodeTools(tap); tap.test('should execure a command', async () => { const result = await tapNodeTools.runCommand('ls -la'); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 6ef5b06..a2e033e 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@git.zone/tstest', - version: '3.6.2', + version: '3.6.3', description: 'A powerful, modern test runner for TypeScript with multi-runtime support (Node.js, Deno, Bun, Chromium) and a batteries-included test framework.' } diff --git a/ts/tstest.classes.runtime.chromium.ts b/ts/tstest.classes.runtime.chromium.ts index eacb0fb..676b3cd 100644 --- a/ts/tstest.classes.runtime.chromium.ts +++ b/ts/tstest.classes.runtime.chromium.ts @@ -83,6 +83,9 @@ export class ChromiumRuntimeAdapter extends RuntimeAdapter { throw new Error('Could not find a free WebSocket port in range 30000-40000'); } + // Stop the smartnetwork instance to release the Rust bridge process + await smartnetwork.stop(); + // Log selected ports for debugging if (!this.logger.options.quiet) { console.log(`Selected ports - HTTP: ${httpPort}, WebSocket: ${wsPort}`); diff --git a/ts_tapbundle/tapbundle.classes.tap.ts b/ts_tapbundle/tapbundle.classes.tap.ts index 55ffcd3..f986fce 100644 --- a/ts_tapbundle/tapbundle.classes.tap.ts +++ b/ts_tapbundle/tapbundle.classes.tap.ts @@ -117,7 +117,8 @@ export class Tap { private settingsManager = new SettingsManager(); private _skipCount = 0; private _filterTags: string[] = []; - + private _cleanupFunctions: Array<() => Promise | void> = []; + constructor() { // Get filter tags from environment if (typeof process !== 'undefined' && process.env && process.env.TSTEST_FILTER_TAGS) { @@ -125,6 +126,14 @@ export class Tap { } } + /** + * Register a cleanup function to be called when tap.start() finishes. + * Use this to tear down resources that would otherwise keep the event loop alive. + */ + public registerCleanup(fn: () => Promise | void) { + this._cleanupFunctions.push(fn); + } + // Fluent test builder public tags(...tags: string[]) { const builder = new TestBuilder(this); @@ -610,6 +619,15 @@ export class Tap { } } + // Run registered cleanup functions (e.g. tapNodeTools stopping SmartNetwork Rust bridge) + for (const cleanupFn of this._cleanupFunctions) { + try { + await cleanupFn(); + } catch (e) { + // Don't let cleanup errors break the test run + } + } + if (optionsArg && optionsArg.throwOnError && failReasons.length > 0) { if (!smartenvInstance.isBrowser && typeof process !== 'undefined') process.exit(1); } diff --git a/ts_tapbundle_serverside/classes.tapnodetools.ts b/ts_tapbundle_serverside/classes.tapnodetools.ts index 3799113..5aa4095 100644 --- a/ts_tapbundle_serverside/classes.tapnodetools.ts +++ b/ts_tapbundle_serverside/classes.tapnodetools.ts @@ -1,12 +1,18 @@ import { TestFileProvider } from './classes.testfileprovider.js'; import * as plugins from './plugins.js'; -class TapNodeTools { +export interface ITapCleanupTarget { + registerCleanup: (fn: () => Promise | void) => void; +} + +export class TapNodeTools { private smartshellInstance: plugins.smartshell.Smartshell; private smartnetworkInstance: plugins.smartnetwork.SmartNetwork; public testFileProvider = new TestFileProvider(); - constructor() {} + constructor(tapArg: ITapCleanupTarget) { + tapArg.registerCleanup(() => this.cleanup()); + } private qenv: plugins.qenv.Qenv; public async getQenv(): Promise { @@ -75,7 +81,7 @@ class TapNodeTools { /** * create and return a smartmongo instance */ - public async createSmartmongo() { + public async createSmartmongo() { const smartmongoMod = await import('@push.rocks/smartmongo'); const smartmongoInstance = new smartmongoMod.SmartMongo(); await smartmongoInstance.start(); @@ -217,6 +223,15 @@ class TapNodeTools { `Could not find ${countArg} consecutive free ports in range ${options.startPort}-${options.endPort}` ); } -} -export const tapNodeTools = new TapNodeTools(); + /** + * Clean up long-lived resources (e.g. the SmartNetwork Rust bridge process) + * so the Node.js event loop can drain naturally. + */ + public async cleanup() { + if (this.smartnetworkInstance) { + await this.smartnetworkInstance.stop(); + this.smartnetworkInstance = null; + } + } +} diff --git a/ts_tapbundle_serverside/readme.md b/ts_tapbundle_serverside/readme.md index a858b6a..495a521 100644 --- a/ts_tapbundle_serverside/readme.md +++ b/ts_tapbundle_serverside/readme.md @@ -30,8 +30,11 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community ## Basic Usage ```typescript -import { tapNodeTools } from '@git.zone/tstest/tapbundle_serverside'; import { tap, expect } from '@git.zone/tstest/tapbundle'; +import { TapNodeTools } from '@git.zone/tstest/tapbundle_serverside'; + +// Create an instance and pass `tap` so cleanup is automatic +const tapNodeTools = new TapNodeTools(tap); tap.test('should start server on free port', async () => { const port = await tapNodeTools.findFreePort(); @@ -41,11 +44,15 @@ tap.test('should start server on free port', async () => { export default tap.start(); ``` +### How cleanup works + +`TapNodeTools` accepts any object with a `registerCleanup()` method (the `tap` instance). On construction, it registers a cleanup callback that stops long-lived background processes (e.g. the SmartNetwork Rust bridge). When `tap.start()` finishes running all tests, it calls all registered cleanup functions automatically, so the Node.js event loop can drain and the process exits cleanly. + ## API Reference -### tapNodeTools +### TapNodeTools -The main singleton instance providing all Node.js-specific utilities. +Construct with a `tap` instance to enable automatic cleanup: ---