commit d96c6bcee8f09f9d4216ba174fac2f36bb31b274 Author: Juergen Kunz Date: Tue Apr 7 17:35:05 2026 +0000 feat(smartmigration): add initial smartmigration package with MongoDB and S3 migration runner diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c7c9e63 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +.nogit/ + +# artifacts +coverage/ +public/ + +# installs +node_modules/ + +# caches +.yarn/ +.cache/ +.rpt2_cache + +# builds +dist/ +dist_*/ + +#------# custom +.claude/* diff --git a/.smartconfig.json b/.smartconfig.json new file mode 100644 index 0000000..4943cca --- /dev/null +++ b/.smartconfig.json @@ -0,0 +1,46 @@ +{ + "@git.zone/cli": { + "projectType": "npm", + "module": { + "githost": "code.foss.global", + "gitscope": "push.rocks", + "gitrepo": "smartmigration", + "description": "Unified migration runner for MongoDB (smartdata) and S3 (smartbucket) — designed to be invoked at SaaS app startup, with semver-based version tracking, sequential step execution, idempotent re-runs, and per-step resumable checkpoints.", + "npmPackagename": "@push.rocks/smartmigration", + "license": "MIT", + "projectDomain": "push.rocks", + "keywords": [ + "migration", + "schema migration", + "data migration", + "mongodb", + "s3", + "smartdata", + "smartbucket", + "saas", + "startup migration", + "semver", + "idempotent", + "ledger", + "rolling deploy" + ] + }, + "release": { + "registries": [ + "https://verdaccio.lossless.digital", + "https://registry.npmjs.org" + ], + "accessLevel": "public" + }, + "services": [ + "mongodb", + "minio" + ] + }, + "@git.zone/tsdoc": { + "legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n" + }, + "@ship.zone/szci": { + "npmGlobalTools": [] + } +} \ No newline at end of file diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..27fc975 --- /dev/null +++ b/changelog.md @@ -0,0 +1,22 @@ +# Changelog + +## 2026-04-07 - 1.1.0 - feat(smartmigration) +add initial smartmigration package with MongoDB and S3 migration runner + +- introduces a builder-style migration API with semver chain validation and structured migration errors +- adds MongoDB and S3 ledger backends with locking, checkpoint persistence, dry-run planning, and fresh-install handling +- includes comprehensive tests and project documentation for the initial public release + +## 2026-04-07 - 1.0.0 - Initial release + +Initial public release of `@push.rocks/smartmigration` — a unified migration runner for MongoDB (smartdata) and S3 (smartbucket). + +- Builder-style step definition: `migration.step(id).from('1.0.0').to('1.1.0').up(async ctx => { ... })` +- Single unified data version (semver), tracked in a ledger +- Mongo ledger (default when `db` provided) backed by smartdata's `EasyStore` +- S3 ledger (default when only `bucket` provided) +- Sequential, idempotent execution: `run()` is a no-op once data is at `targetVersion` +- Per-step lock with TTL to serialize concurrent SaaS instances +- Resumable steps via `.resumable()` and `ctx.checkpoint` +- Fresh-install fast path via `freshInstallVersion` option +- Dry-run mode diff --git a/license b/license new file mode 100644 index 0000000..f4fe72a --- /dev/null +++ b/license @@ -0,0 +1,19 @@ +Copyright (c) 2026 Task Venture Capital GmbH (hello@task.vc) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/package.json b/package.json new file mode 100644 index 0000000..e7035f9 --- /dev/null +++ b/package.json @@ -0,0 +1,84 @@ +{ + "name": "@push.rocks/smartmigration", + "version": "1.0.0", + "private": false, + "description": "Unified migration runner for MongoDB (smartdata) and S3 (smartbucket) — designed to be invoked at SaaS app startup, with semver-based version tracking, sequential step execution, idempotent re-runs, and per-step resumable checkpoints.", + "main": "dist_ts/index.js", + "typings": "dist_ts/index.d.ts", + "type": "module", + "author": "Lossless GmbH", + "license": "MIT", + "scripts": { + "test": "(tstest test/**/test*.ts --verbose --timeout 120 --logfile)", + "build": "(tsbuild tsfolders --allowimplicitany)", + "format": "(gitzone format)", + "buildDocs": "tsdoc" + }, + "devDependencies": { + "@git.zone/tsbuild": "^4.4.0", + "@git.zone/tsrun": "^2.0.2", + "@git.zone/tstest": "^3.6.0", + "@push.rocks/qenv": "^6.1.3", + "@push.rocks/smartdata": "^7.1.7", + "@push.rocks/smartbucket": "^4.6.0", + "@types/node": "^25.5.0", + "typescript": "^6.0.2" + }, + "dependencies": { + "@push.rocks/smartlog": "^3.2.1", + "@push.rocks/smartversion": "^3.1.0" + }, + "peerDependencies": { + "@push.rocks/smartdata": "^7.1.7", + "@push.rocks/smartbucket": "^4.6.0" + }, + "peerDependenciesMeta": { + "@push.rocks/smartdata": { + "optional": true + }, + "@push.rocks/smartbucket": { + "optional": true + } + }, + "files": [ + "ts/**/*", + "dist/**/*", + "dist_*/**/*", + "dist_ts/**/*", + ".smartconfig.json", + "readme.md", + "changelog.md" + ], + "browserslist": [ + "last 1 chrome versions" + ], + "keywords": [ + "migration", + "schema migration", + "data migration", + "mongodb", + "s3", + "smartdata", + "smartbucket", + "saas", + "startup migration", + "semver", + "idempotent", + "ledger", + "rolling deploy" + ], + "homepage": "https://code.foss.global/push.rocks/smartmigration#readme", + "repository": { + "type": "git", + "url": "https://code.foss.global/push.rocks/smartmigration.git" + }, + "bugs": { + "url": "https://code.foss.global/push.rocks/smartmigration/issues" + }, + "pnpm": { + "overrides": {}, + "onlyBuiltDependencies": [ + "mongodb-memory-server" + ] + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..298a364 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,8034 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@push.rocks/smartlog': + specifier: ^3.2.1 + version: 3.2.1 + '@push.rocks/smartversion': + specifier: ^3.1.0 + version: 3.1.0 + devDependencies: + '@git.zone/tsbuild': + specifier: ^4.4.0 + version: 4.4.0 + '@git.zone/tsrun': + specifier: ^2.0.2 + version: 2.0.2 + '@git.zone/tstest': + specifier: ^3.6.0 + version: 3.6.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(socks@2.8.7)(typescript@6.0.2) + '@push.rocks/qenv': + specifier: ^6.1.3 + version: 6.1.3 + '@push.rocks/smartbucket': + specifier: ^4.6.0 + version: 4.6.0 + '@push.rocks/smartdata': + specifier: ^7.1.7 + version: 7.1.7(socks@2.8.7) + '@types/node': + specifier: ^25.5.0 + version: 25.5.2 + typescript: + specifier: ^6.0.2 + version: 6.0.2 + +packages: + + '@api.global/typedrequest-interfaces@2.0.2': + resolution: {integrity: sha512-D+mkr4IiUZ/eUgrdp5jXjBKOW/iuMcl0z2ZLQsLLypKX/psFGD3viZJ58FNRa+/1OSM38JS5wFyoWl8oPEFLrw==} + + '@api.global/typedrequest-interfaces@3.0.19': + resolution: {integrity: sha512-uuHUXJeOy/inWSDrwD0Cwax2rovpxYllDhM2RWh+6mVpQuNmZ3uw6IVg6dA2G1rOe24Ebs+Y9SzEogo+jYN7vw==} + + '@api.global/typedrequest@3.3.0': + resolution: {integrity: sha512-Jwobqla+9k2IBG0duwrCFtc6GU6wsvHS3f0gJJsxTrpapylBW1YSF7NnGHPGs7F9hbATsO6IoUBpR2ScoKyGJA==} + + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/crc32c@5.2.0': + resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} + + '@aws-crypto/sha1-browser@5.2.0': + resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-s3@3.1025.0': + resolution: {integrity: sha512-9Byz2fPnuGRRL8DTTD5bYPl1Iwm+ysLiCMgptffa3lNkVLCiUZc5e5TAaOjk0MvyeXieq+jn35AmQL6cgN2KHQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.973.26': + resolution: {integrity: sha512-A/E6n2W42ruU+sfWk+mMUOyVXbsSgGrY3MJ9/0Az5qUdG67y8I6HYzzoAa+e/lzxxl1uCYmEL6BTMi9ZiZnplQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/crc64-nvme@3.972.5': + resolution: {integrity: sha512-2VbTstbjKdT+yKi8m7b3a9CiVac+pL/IY2PHJwsaGkkHmuuqkJZIErPck1h6P3T9ghQMLSdMPyW6Qp7Di5swFg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.24': + resolution: {integrity: sha512-FWg8uFmT6vQM7VuzELzwVo5bzExGaKHdubn0StjgrcU5FvuLExUe+k06kn/40uKv59rYzhez8eFNM4yYE/Yb/w==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-http@3.972.26': + resolution: {integrity: sha512-CY4ppZ+qHYqcXqBVi//sdHST1QK3KzOEiLtpLsc9W2k2vfZPKExGaQIsOwcyvjpjUEolotitmd3mUNY56IwDEA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-ini@3.972.28': + resolution: {integrity: sha512-wXYvq3+uQcZV7k+bE4yDXCTBdzWTU9x/nMiKBfzInmv6yYK1veMK0AKvRfRBd72nGWYKcL6AxwiPg9z/pYlgpw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.28': + resolution: {integrity: sha512-ZSTfO6jqUTCysbdBPtEX5OUR//3rbD0lN7jO3sQeS2Gjr/Y+DT6SbIJ0oT2cemNw3UzKu97sNONd1CwNMthuZQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-node@3.972.29': + resolution: {integrity: sha512-clSzDcvndpFJAggLDnDb36sPdlZYyEs5Zm6zgZjjUhwsJgSWiWKwFIXUVBcbruidNyBdbpOv2tNDL9sX8y3/0g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-process@3.972.24': + resolution: {integrity: sha512-Q2k/XLrFXhEztPHqj4SLCNID3hEPdlhh1CDLBpNnM+1L8fq7P+yON9/9M1IGN/dA5W45v44ylERfXtDAlmMNmw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-sso@3.972.28': + resolution: {integrity: sha512-IoUlmKMLEITFn1SiCTjPfR6KrE799FBo5baWyk/5Ppar2yXZoUdaRqZzJzK6TcJxx450M8m8DbpddRVYlp5R/A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.972.28': + resolution: {integrity: sha512-d+6h0SD8GGERzKe27v5rOzNGKOl0D+l0bWJdqrxH8WSQzHzjsQFIAPgIeOTUwBHVsKKwtSxc91K/SWax6XgswQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-bucket-endpoint@3.972.8': + resolution: {integrity: sha512-WR525Rr2QJSETa9a050isktyWi/4yIGcmY3BQ1kpHqb0LqUglQHCS8R27dTJxxWNZvQ0RVGtEZjTCbZJpyF3Aw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-expect-continue@3.972.8': + resolution: {integrity: sha512-5DTBTiotEES1e2jOHAq//zyzCjeMB78lEHd35u15qnrid4Nxm7diqIf9fQQ3Ov0ChH1V3Vvt13thOnrACmfGVQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-flexible-checksums@3.974.6': + resolution: {integrity: sha512-YckB8k1ejbyCg/g36gUMFLNzE4W5cERIa4MtsdO+wpTmJEP0+TB7okWIt7d8TDOvnb7SwvxJ21E4TGOBxFpSWQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-host-header@3.972.8': + resolution: {integrity: sha512-wAr2REfKsqoKQ+OkNqvOShnBoh+nkPurDKW7uAeVSu6kUECnWlSJiPvnoqxGlfousEY/v9LfS9sNc46hjSYDIQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-location-constraint@3.972.8': + resolution: {integrity: sha512-KaUoFuoFPziIa98DSQsTPeke1gvGXlc5ZGMhy+b+nLxZ4A7jmJgLzjEF95l8aOQN2T/qlPP3MrAyELm8ExXucw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-logger@3.972.8': + resolution: {integrity: sha512-CWl5UCM57WUFaFi5kB7IBY1UmOeLvNZAZ2/OZ5l20ldiJ3TiIz1pC65gYj8X0BCPWkeR1E32mpsCk1L1I4n+lA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.972.9': + resolution: {integrity: sha512-/Wt5+CT8dpTFQxEJ9iGy/UGrXr7p2wlIOEHvIr/YcHYByzoLjrqkYqXdJjd9UIgWjv7eqV2HnFJen93UTuwfTQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.972.27': + resolution: {integrity: sha512-gomO6DZwx+1D/9mbCpcqO5tPBqYBK7DtdgjTIjZ4yvfh/S7ETwAPS0XbJgP2JD8Ycr5CwVrEkV1sFtu3ShXeOw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-ssec@3.972.8': + resolution: {integrity: sha512-wqlK0yO/TxEC2UsY9wIlqeeutF6jjLe0f96Pbm40XscTo57nImUk9lBcw0dPgsm0sppFtAkSlDrfpK+pC30Wqw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-user-agent@3.972.28': + resolution: {integrity: sha512-cfWZFlVh7Va9lRay4PN2A9ARFzaBYcA097InT5M2CdRS05ECF5yaz86jET8Wsl2WcyKYEvVr/QNmKtYtafUHtQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/nested-clients@3.996.18': + resolution: {integrity: sha512-c7ZSIXrESxHKx2Mcopgd8AlzZgoXMr20fkx5ViPWPOLBvmyhw9VwJx/Govg8Ef/IhEon5R9l53Z8fdYSEmp6VA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/region-config-resolver@3.972.10': + resolution: {integrity: sha512-1dq9ToC6e070QvnVhhbAs3bb5r6cQ10gTVc6cyRV5uvQe7P138TV2uG2i6+Yok4bAkVAcx5AqkTEBUvWEtBlsQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.996.15': + resolution: {integrity: sha512-Ukw2RpqvaL96CjfH/FgfBmy/ZosHBqoHBCFsN61qGg99F33vpntIVii8aNeh65XuOja73arSduskoa4OJea9RQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1021.0': + resolution: {integrity: sha512-TKY6h9spUk3OLs5v1oAgW9mAeBE3LAGNBwJokLy96wwmd4W2v/tYlXseProyed9ValDj2u1jK/4Rg1T+1NXyJA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.973.6': + resolution: {integrity: sha512-Atfcy4E++beKtwJHiDln2Nby8W/mam64opFPTiHEqgsthqeydFS1pY+OUlN1ouNOmf8ArPU/6cDS65anOP3KQw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-arn-parser@3.972.3': + resolution: {integrity: sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-endpoints@3.996.5': + resolution: {integrity: sha512-Uh93L5sXFNbyR5sEPMzUU8tJ++Ku97EY4udmC01nB8Zu+xfBPwpIwJ6F7snqQeq8h2pf+8SGN5/NoytfKgYPIw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-locate-window@3.965.5': + resolution: {integrity: sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-user-agent-browser@3.972.8': + resolution: {integrity: sha512-B3KGXJviV2u6Cdw2SDY2aDhoJkVfY/Q/Trwk2CMSkikE1Oi6gRzxhvhIfiRpHfmIsAhV4EA54TVEX8K6CbHbkA==} + + '@aws-sdk/util-user-agent-node@3.973.14': + resolution: {integrity: sha512-vNSB/DYaPOyujVZBg/zUznH9QC142MaTHVmaFlF7uzzfg3CgT9f/l4C0Yi+vU/tbBhxVcXVB90Oohk5+o+ZbWw==} + engines: {node: '>=20.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.972.16': + resolution: {integrity: sha512-iu2pyvaqmeatIJLURLqx9D+4jKAdTH20ntzB6BFwjyN7V960r4jK32mx0Zf7YbtOYAbmbtQfDNuL60ONinyw7A==} + engines: {node: '>=20.0.0'} + + '@aws/lambda-invoke-store@0.2.4': + resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==} + engines: {node: '>=18.0.0'} + + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + + '@borewit/text-codec@0.2.2': + resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + + '@cfworker/json-schema@4.1.1': + resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + + '@configvault.io/interfaces@1.0.17': + resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==} + + '@design.estate/dees-comms@1.0.30': + resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==} + + '@design.estate/dees-domtools@2.5.4': + resolution: {integrity: sha512-IGyVKl1XMXHVCpPQXX6wSnGbD4S2Q1XkJCuuXZotu4Q86HTiALyfyZi0RouCKv3zxCSMvZHpFWVoh2DgF/3R3g==} + + '@design.estate/dees-element@2.2.4': + resolution: {integrity: sha512-O9cA6flBMMd+pBwMQrZXwAWel9yVxgokolb+Em6gvkXxPJ0P/B5UDn4Vc2d4ts3ta55PTBm+l2dPeDVGx/bl7Q==} + + '@emnapi/core@1.9.2': + resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} + + '@emnapi/runtime@1.9.2': + resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@git.zone/tsbuild@4.4.0': + resolution: {integrity: sha512-98igHfppi6blFYDyzNukNkj4FUO5ZlyXEaSyJh8vCkkZM8SyAgfZj+NUWA1D1iaPXE58UvK1Pt/o8p8iI9UHHw==} + hasBin: true + + '@git.zone/tsbundle@2.10.0': + resolution: {integrity: sha512-dw2VFlgKssDlCxg92wSPiiAKwfCjJBOEOYXq1xO91OpjQLOkyogCxSLy0jzQ2BYnt4qmBnapjamzYzVjCr4CWg==} + hasBin: true + + '@git.zone/tspublish@1.11.5': + resolution: {integrity: sha512-3tCGhVbH6S/17n3A6Tc6H+ncRdxxbTT0ABcj8S1wRLA8YuBSj9bY7k6uj/iFRy/B/OepB94m1goCiaWESdcZYg==} + hasBin: true + + '@git.zone/tsrun@2.0.2': + resolution: {integrity: sha512-Rnp/wYHzI8A1pVBKOOePRJgQiBZdW+GEjpQk2uhvXz6A+ljUV2SXKc7NpQVVDsjEZaNFeAI9jMYOdk3lm3yMDA==} + hasBin: true + + '@git.zone/tstest@3.6.3': + resolution: {integrity: sha512-xvHZia3VEYO3ztXNqN3+ytF07vA2imZJwpD7GOv/wVM/hY58bUVvs/YnJ0C4nwiCGiHV87LU27NDEGfoNPYZcw==} + hasBin: true + + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.4': + 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==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@inquirer/checkbox@3.0.1': + resolution: {integrity: sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ==} + engines: {node: '>=18'} + + '@inquirer/confirm@4.0.1': + resolution: {integrity: sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w==} + engines: {node: '>=18'} + + '@inquirer/core@9.2.1': + resolution: {integrity: sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==} + engines: {node: '>=18'} + + '@inquirer/editor@3.0.1': + resolution: {integrity: sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q==} + engines: {node: '>=18'} + + '@inquirer/expand@3.0.1': + resolution: {integrity: sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ==} + engines: {node: '>=18'} + + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/input@3.0.1': + resolution: {integrity: sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg==} + engines: {node: '>=18'} + + '@inquirer/number@2.0.1': + resolution: {integrity: sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ==} + engines: {node: '>=18'} + + '@inquirer/password@3.0.1': + resolution: {integrity: sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ==} + engines: {node: '>=18'} + + '@inquirer/prompts@6.0.1': + resolution: {integrity: sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A==} + engines: {node: '>=18'} + + '@inquirer/rawlist@3.0.1': + resolution: {integrity: sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ==} + engines: {node: '>=18'} + + '@inquirer/search@2.0.1': + resolution: {integrity: sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg==} + engines: {node: '>=18'} + + '@inquirer/select@3.0.1': + resolution: {integrity: sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q==} + engines: {node: '>=18'} + + '@inquirer/type@2.0.0': + resolution: {integrity: sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==} + engines: {node: '>=18'} + + '@isaacs/cliui@9.0.0': + resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==} + engines: {node: '>=18'} + + '@jimp/core@1.6.0': + resolution: {integrity: sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==} + engines: {node: '>=18'} + + '@jimp/diff@1.6.0': + resolution: {integrity: sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==} + engines: {node: '>=18'} + + '@jimp/file-ops@1.6.0': + resolution: {integrity: sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==} + engines: {node: '>=18'} + + '@jimp/js-bmp@1.6.0': + resolution: {integrity: sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==} + engines: {node: '>=18'} + + '@jimp/js-gif@1.6.0': + resolution: {integrity: sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==} + engines: {node: '>=18'} + + '@jimp/js-jpeg@1.6.0': + resolution: {integrity: sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==} + engines: {node: '>=18'} + + '@jimp/js-png@1.6.0': + resolution: {integrity: sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==} + engines: {node: '>=18'} + + '@jimp/js-tiff@1.6.0': + resolution: {integrity: sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==} + engines: {node: '>=18'} + + '@jimp/plugin-blit@1.6.0': + resolution: {integrity: sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==} + engines: {node: '>=18'} + + '@jimp/plugin-blur@1.6.0': + resolution: {integrity: sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==} + engines: {node: '>=18'} + + '@jimp/plugin-circle@1.6.0': + resolution: {integrity: sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==} + engines: {node: '>=18'} + + '@jimp/plugin-color@1.6.0': + resolution: {integrity: sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==} + engines: {node: '>=18'} + + '@jimp/plugin-contain@1.6.0': + resolution: {integrity: sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==} + engines: {node: '>=18'} + + '@jimp/plugin-cover@1.6.0': + resolution: {integrity: sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==} + engines: {node: '>=18'} + + '@jimp/plugin-crop@1.6.0': + resolution: {integrity: sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==} + engines: {node: '>=18'} + + '@jimp/plugin-displace@1.6.0': + resolution: {integrity: sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==} + engines: {node: '>=18'} + + '@jimp/plugin-dither@1.6.0': + resolution: {integrity: sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==} + engines: {node: '>=18'} + + '@jimp/plugin-fisheye@1.6.0': + resolution: {integrity: sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==} + engines: {node: '>=18'} + + '@jimp/plugin-flip@1.6.0': + resolution: {integrity: sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==} + engines: {node: '>=18'} + + '@jimp/plugin-hash@1.6.0': + resolution: {integrity: sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==} + engines: {node: '>=18'} + + '@jimp/plugin-mask@1.6.0': + resolution: {integrity: sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==} + engines: {node: '>=18'} + + '@jimp/plugin-print@1.6.0': + resolution: {integrity: sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==} + engines: {node: '>=18'} + + '@jimp/plugin-quantize@1.6.0': + resolution: {integrity: sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==} + engines: {node: '>=18'} + + '@jimp/plugin-resize@1.6.0': + resolution: {integrity: sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==} + engines: {node: '>=18'} + + '@jimp/plugin-rotate@1.6.0': + resolution: {integrity: sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==} + engines: {node: '>=18'} + + '@jimp/plugin-threshold@1.6.0': + resolution: {integrity: sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==} + engines: {node: '>=18'} + + '@jimp/types@1.6.0': + resolution: {integrity: sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==} + engines: {node: '>=18'} + + '@jimp/utils@1.6.0': + resolution: {integrity: sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==} + engines: {node: '>=18'} + + '@lit-labs/ssr-dom-shim@1.5.1': + resolution: {integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==} + + '@lit/reactive-element@2.1.2': + resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==} + + '@mixmark-io/domino@2.2.0': + resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==} + + '@module-federation/error-codes@0.22.0': + resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} + + '@module-federation/runtime-core@0.22.0': + resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} + + '@module-federation/runtime-tools@0.22.0': + resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} + + '@module-federation/runtime@0.22.0': + resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} + + '@module-federation/sdk@0.22.0': + resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} + + '@module-federation/webpack-bundler-runtime@0.22.0': + resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} + + '@mongodb-js/saslprep@1.4.6': + resolution: {integrity: sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==} + + '@napi-rs/wasm-runtime@1.0.7': + resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + + '@napi-rs/wasm-runtime@1.1.2': + resolution: {integrity: sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@oxc-project/types@0.122.0': + resolution: {integrity: sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==} + + '@pdf-lib/standard-fonts@1.0.0': + resolution: {integrity: sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==} + + '@pdf-lib/upng@1.0.1': + resolution: {integrity: sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==} + + '@peculiar/asn1-cms@2.6.1': + resolution: {integrity: sha512-vdG4fBF6Lkirkcl53q6eOdn3XYKt+kJTG59edgRZORlg/3atWWEReRCx5rYE1ZzTTX6vLK5zDMjHh7vbrcXGtw==} + + '@peculiar/asn1-csr@2.6.1': + resolution: {integrity: sha512-WRWnKfIocHyzFYQTka8O/tXCiBquAPSrRjXbOkHbO4qdmS6loffCEGs+rby6WxxGdJCuunnhS2duHURhjyio6w==} + + '@peculiar/asn1-ecc@2.6.1': + resolution: {integrity: sha512-+Vqw8WFxrtDIN5ehUdvlN2m73exS2JVG0UAyfVB31gIfor3zWEAQPD+K9ydCxaj3MLen9k0JhKpu9LqviuCE1g==} + + '@peculiar/asn1-pfx@2.6.1': + resolution: {integrity: sha512-nB5jVQy3MAAWvq0KY0R2JUZG8bO/bTLpnwyOzXyEh/e54ynGTatAR+csOnXkkVD9AFZ2uL8Z7EV918+qB1qDvw==} + + '@peculiar/asn1-pkcs8@2.6.1': + resolution: {integrity: sha512-JB5iQ9Izn5yGMw3ZG4Nw3Xn/hb/G38GYF3lf7WmJb8JZUydhVGEjK/ZlFSWhnlB7K/4oqEs8HnfFIKklhR58Tw==} + + '@peculiar/asn1-pkcs9@2.6.1': + resolution: {integrity: sha512-5EV8nZoMSxeWmcxWmmcolg22ojZRgJg+Y9MX2fnE2bGRo5KQLqV5IL9kdSQDZxlHz95tHvIq9F//bvL1OeNILw==} + + '@peculiar/asn1-rsa@2.6.1': + resolution: {integrity: sha512-1nVMEh46SElUt5CB3RUTV4EG/z7iYc7EoaDY5ECwganibQPkZ/Y2eMsTKB/LeyrUJ+W/tKoD9WUqIy8vB+CEdA==} + + '@peculiar/asn1-schema@2.6.0': + resolution: {integrity: sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg==} + + '@peculiar/asn1-x509-attr@2.6.1': + resolution: {integrity: sha512-tlW6cxoHwgcQghnJwv3YS+9OO1737zgPogZ+CgWRUK4roEwIPzRH4JEiG770xe5HX2ATfCpmX60gurfWIF9dcQ==} + + '@peculiar/asn1-x509@2.6.1': + resolution: {integrity: sha512-O9jT5F1A2+t3r7C4VT7LYGXqkGLK7Kj1xFpz7U0isPrubwU5PbDoyYtx6MiGst29yq7pXN5vZbQFKRCP+lLZlA==} + + '@peculiar/x509@1.14.3': + resolution: {integrity: sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==} + engines: {node: '>=20.0.0'} + + '@pnpm/config.env-replace@1.1.0': + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + + '@pnpm/network.ca-file@1.0.2': + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} + + '@pnpm/npm-conf@3.0.2': + resolution: {integrity: sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==} + engines: {node: '>=12'} + + '@puppeteer/browsers@2.13.0': + resolution: {integrity: sha512-46BZJYJjc/WwmKjsvDFykHtXrtomsCIrwYQPOP7VfMJoZY2bsDF9oROBABR3paDjDcmkUye1Pb1BqdcdiipaWA==} + engines: {node: '>=18'} + hasBin: true + + '@push.rocks/consolecolor@2.0.3': + resolution: {integrity: sha512-hA+m0BMqEwZNSAS7c2aQFfoPkpX/dNdsHzkdLdeERUOy7BLacb9ItTUofGtjtginP0yDj4NSpqSjNYyX3Y8Y/w==} + + '@push.rocks/early@4.0.4': + resolution: {integrity: sha512-ak6/vqZ1PlFV08fSFQ6UwiBrr+K6IsfieZWWzT7eex1Ls6GvWEi8wZ3REFDPJq/qckNLWSgEy0EsqzRtltkaCA==} + + '@push.rocks/isounique@1.0.5': + resolution: {integrity: sha512-Z0BVqZZOCif1THTbIKWMgg0wxCzt9CyBtBBqQJiZ+jJ0KlQFrQHNHrPt81/LXe/L4x0cxWsn0bpL6W5DNSvNLw==} + + '@push.rocks/levelcache@3.2.0': + resolution: {integrity: sha512-Ch0Oguta2I0SVi704kHghhBcgfyfS92ua1elRu9d8X1/9LMRYuqvvBAnyXyFxQzI3S8q8QC6EkRdd8CAAYSzRg==} + + '@push.rocks/lik@6.4.0': + resolution: {integrity: sha512-GCdXyF2a6NP+i0W6Mib1PjtA6JGrl6Ae17SbaQwqTscn4JHNta6xm9r+D8/b83XGZsoU903FlJZli3YqJCxT9Q==} + + '@push.rocks/mongodump@1.1.0': + resolution: {integrity: sha512-kW0ZUGyf1e4nwloVwBQjNId+MzgTcNS834C+RxH21i1NqyOubbpWZtJtPP+K+s35nSJRyCTy3ICfBMdDBTAm2w==} + + '@push.rocks/qenv@6.1.3': + resolution: {integrity: sha512-+z2hsAU/7CIgpYLFqvda8cn9rUBMHqLdQLjsFfRn5jPoD7dJ5rFlpkbhfM4Ws8mHMniwWaxGKo+q/YBhtzRBLg==} + + '@push.rocks/smartarchive@4.2.4': + resolution: {integrity: sha512-uiqVAXPxmr8G5rv3uZvZFMOCt8l7cZC3nzvsy4YQqKf/VkPhKIEX+b7LkAeNlxPSYUiBQUkNRoawg9+5BaMcHg==} + + '@push.rocks/smartbrowser@2.0.11': + resolution: {integrity: sha512-Rj3+VodlFbW7CkvXqYxH4dEhtbYy987gVY7wsM76B+ipvnkSfjfEGuKUeMfKe4DscUBSmhlbJVYEYaH8RafUoQ==} + + '@push.rocks/smartbucket@3.3.10': + resolution: {integrity: sha512-0H2MioALspC8Aj0Q1FPCs2w4k2u9oJg7Q5yM8+1TZo7aRfrdxgM5HQ7z3apUaqC3ZEDewW6vSlttjHFHhMEC3A==} + + '@push.rocks/smartbucket@4.6.0': + resolution: {integrity: sha512-F45ydPscGN71eIvSzX9axiBWWSOT79S8YwfaaUC3OciYTYiEm7nvJf6ox16ZOGsOw+s5ZDMNOs7IhZTZ4npCBA==} + + '@push.rocks/smartbuffer@3.0.5': + resolution: {integrity: sha512-pWYF08Mn8s/KF/9nHRk7pZPzuMjmYVQay2c5gGexdayxn1W4eCSYYhWH73vR2JBfGeGq/izbRNuUuEaIEeTIKA==} + + '@push.rocks/smartcache@1.0.18': + resolution: {integrity: sha512-3+cmLu9chbnmi4yD4kjlFP/Tn4NReaZIoicEcGTtwbcokTrSDMs3YPdJzIpDZkAs83PW7OcVSHa3Ak5KU5OWzA==} + + '@push.rocks/smartcli@4.0.20': + resolution: {integrity: sha512-gCo4ItvsPj8WoVAJw/6vkuoGA5FtIoACux2ktcCeH0nrFe7/xGR6waJ1aZcYAi7QN4gi52TlsgwuKz7BzXqhmQ==} + + '@push.rocks/smartclickhouse@2.2.0': + resolution: {integrity: sha512-eTzKiREIPSzL1kPkVyD6vEbn+WV/DvQqDjP67VlhNlQGbRcemnJG/eLrUUR1ytmdIqnsZGEK6UYBgyj5nhzLNQ==} + + '@push.rocks/smartconfig@6.1.0': + resolution: {integrity: sha512-B+xh63PhGAsSwuRyCKXr4PAjJ4HoVKhNysi67OGY6gGqGm6uopgEW1cvrUZ7T5ZSck9KlVx7ZTugbqm6dqBK1Q==} + + '@push.rocks/smartcrypto@2.0.4': + resolution: {integrity: sha512-1+/5bsjyataf5uUkUNnnVXGRAt+gHVk1KDzozjTqgqJxHvQk1d9fVDohL6CxUhUucTPtu5VR5xNBiV8YCDuGyw==} + + '@push.rocks/smartdata@7.1.7': + resolution: {integrity: sha512-HDI/Q9dKybfsJ68oCzlE+S63Xpij9qXnMfi28yznKP0Li1ECVZZMDDGIW5IjsXlHjO+Q+RJMcVd72Pjt3QLY5Q==} + + '@push.rocks/smartdelay@3.0.5': + resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==} + + '@push.rocks/smartdns@7.9.0': + resolution: {integrity: sha512-1nDUfyXQo6j9HTUfcjE+BLeAv9QZ7WtAsM1V28zIoFdUpjNg/5g382L024H73PHsxh6lSYNhYYmFvWqzFQhXKg==} + + '@push.rocks/smartenv@5.0.13': + resolution: {integrity: sha512-ACXmUcHZHl2CF2jnVuRw9saRRrZvJblCRs2d+K5aLR1DfkYFX3eA21kcMlKeLisI3aGNbIj9vz/rowN5qkRkfA==} + + '@push.rocks/smartenv@6.0.0': + resolution: {integrity: sha512-ktW5MqOFs0492sB4vrvl4lgRFQ/sQ4AyREgB+sCIzGqszHWGVvGXR95Y2a3z66jkLPYML2CUWHzmMlfv8fkG+A==} + + '@push.rocks/smarterror@2.0.1': + resolution: {integrity: sha512-iCcH1D8tlDJgMFsaJ6lhdOTKhbU0KoprNv9MRP9o7691QOx4JEDXiHtr/lNtxVo8BUtdb9CF6kazaknO9KuORA==} + + '@push.rocks/smartexit@1.1.1': + resolution: {integrity: sha512-UwcVJbp7vzzDM9RQmnfTaVOJ+DK127lAC5gwyfKU2GfPAv0Jng62Sv601otP+jnly9nRt5fUuttNHDl34Mjn3g==} + + '@push.rocks/smartexit@2.0.3': + resolution: {integrity: sha512-ZWpZ3Elorpv/rKtUcCUejUHG4BIE5B3QWysBAgb7lTcA7y0vGdFY32Y5/Q5tHpZM6PPxl/WTdUOYtSojQTq+pA==} + + '@push.rocks/smartexpect@2.5.0': + resolution: {integrity: sha512-yoyuCoQ3tTiAriuvF+/09fNbVfFnacudL2SwHSzPhX/ugaE7VTSWXQ9A34eKOWvil0MPyDcOY36fVZDxvrPd8A==} + + '@push.rocks/smartfile-interfaces@1.0.7': + resolution: {integrity: sha512-MeOl/200UOvSO4Pgq/DVFiBVZpL9gjOBQM+4XYNjSxda8c6VBvchHAntaFLQUlO8U1ckNaP9i+nMO4O4/0ymyw==} + + '@push.rocks/smartfile@11.2.7': + resolution: {integrity: sha512-8Yp7/sAgPpWJBHohV92ogHWKzRomI5MEbSG6b5W2n18tqwfAmjMed0rQvsvGrSBlnEWCKgoOrYIIZbLO61+J0Q==} + + '@push.rocks/smartfile@13.1.2': + resolution: {integrity: sha512-DaEhwmnGEpX4coeeToaw4cZe3pNBhH7CY1iGr+d3pIXihozREvzzAR9/0i2r7bUXXL5+Lgy8YYIk5ZS+fwxMKA==} + + '@push.rocks/smartfs@1.5.0': + resolution: {integrity: sha512-QwMD44HgX3d9PPxUwR0uS+0PEMtesKvKbZR+s4pezL2er6oPneKJMLkO6TJPvJ38nug6Lmlk9Bu7UrwR2kS3Vw==} + + '@push.rocks/smartguard@3.1.0': + resolution: {integrity: sha512-J23q84f1O+TwFGmd4lrO9XLHUh2DaLXo9PN/9VmTWYzTkQDv5JehmifXVI0esophXcCIfbdIu6hbt7/aHlDF4A==} + + '@push.rocks/smarthash@3.2.6': + resolution: {integrity: sha512-Mq/WNX0Tjjes3X1gHd/ZBwOOKSrAG/Z3Xoc0OcCm3P20WKpniihkMpsnlE7wGjvpHLi/ZRe/XkB3KC3d5r9X4g==} + + '@push.rocks/smartinteract@2.0.16': + resolution: {integrity: sha512-eltvVRRUKBKd77DSFA4DPY2g4V4teZLNe8A93CDy/WglglYcUjxMoLY/b0DFTWCWKYT+yjk6Fe6p0FRrvX9Yvg==} + + '@push.rocks/smartjimp@1.2.0': + resolution: {integrity: sha512-SPz8p2ZuphNqIXK/UDsNFrnpJn/jr6FbuBSMQc0V2v2ffQIF32ZqktKQpXpitiqD1K5JEYS56JAhlYHgrAu7yw==} + + '@push.rocks/smartjson@5.2.0': + resolution: {integrity: sha512-710e8UwovRfPgUtaBHcd6unaODUjV5fjxtGcGCqtaTcmvOV6VpasdVfT66xMDzQmWH2E9ZfHDJeso9HdDQzNQA==} + + '@push.rocks/smartjson@6.0.0': + resolution: {integrity: sha512-FYfJnmukt66WePn6xrVZ3BLmRQl9W82LcsICK3VU9sGW7kasig090jKXPm+yX8ibQcZAO/KyR/Q8tMIYZNxGew==} + + '@push.rocks/smartlog-destination-local@9.0.2': + resolution: {integrity: sha512-htzIY+4+hU61Z2J4Oz+IHnAB3RGe+fpS0VKCKnAoppZqzMWnJ3UOgYIyr4djDBy2WtgpXV/16KdisKrOmwuuvw==} + + '@push.rocks/smartlog-interfaces@3.0.2': + resolution: {integrity: sha512-8hGRTJehbsFSJxLhCQkA018mZtXVPxPTblbg9VaE/EqISRzUw+eosJ2EJV7M4Qu0eiTJZjnWnNLn8CkD77ziWw==} + + '@push.rocks/smartlog@3.2.1': + resolution: {integrity: sha512-x9/P59pfzY6HOGYmYrhqmoRl/pliTVx44g2Vbb8dIr/0zA39cAJHlPze1+UGncn37XKGmutK2iLSsJLEsexD0A==} + + '@push.rocks/smartmarkdown@3.0.3': + resolution: {integrity: sha512-9KhKZxDQKPk4P/2CYdVqJa5dpGfTA8w1cxqoVZL3e8RPA7EGxbdYEqMp0n2d9mth0btk/m0KHHV+G09LfCVeBw==} + + '@push.rocks/smartmatch@2.0.0': + resolution: {integrity: sha512-MBzP++1yNIBeox71X6VxpIgZ8m4bXnJpZJ4nWVH6IWpmO38MXTu4X0QF8tQnyT4LFcwvc9iiWaD15cstHa7Mmw==} + + '@push.rocks/smartmime@2.0.4': + resolution: {integrity: sha512-mG6lRBLr5nF+GLZmgCcdjhdDsmTtJWBFZDCa1eJ8Au9TvUzbPW0fY5aqJBb3UwfyZzH6St8Th9cJSXjagOQkYA==} + + '@push.rocks/smartmongo@5.1.1': + resolution: {integrity: sha512-OFzEjTlXQ0zN9KYewhJRJxxX8bdVO7sl5H4RRd0F0PyU4FEXesLF8Sm4rsCFtQW1ifGQEBOcoruRkoiWz918Ug==} + + '@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==} + + '@push.rocks/smartobject@1.0.12': + resolution: {integrity: sha512-xSMiqXiZXXUOixT3QIPsOUKOWjL3YA/1h9/YTiCzqs5C0D3tyfTbojnfcp6YbKZoBzans2I5LghaDHsGid2DKQ==} + + '@push.rocks/smartpath@6.0.0': + resolution: {integrity: sha512-r94u1MbBaIOSy+517PZp2P7SuZPSe9LkwJ8l3dXQKHeIOri/zDxk/RQPiFM+j4N9301ztkRyhvRj7xgUDroOsg==} + + '@push.rocks/smartpdf@4.2.0': + resolution: {integrity: sha512-+egzby5QKJGO10MDvWp+N69cJ8i5M354l9ntc+uLRpxuq/FEY9kigpRwMvRYF5qwOBTuGTLqvmvILzlLtboAQg==} + + '@push.rocks/smartpromise@4.2.3': + resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==} + + '@push.rocks/smartpuppeteer@2.0.5': + resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==} + + '@push.rocks/smartrequest@2.1.0': + resolution: {integrity: sha512-3eHLTRInHA+u+W98TqJwgTES7rRimBAsJC4JxVNQC3UUezmblAhM5/TIQsEBQTsbjAY8SeQKy6NHzW6iTiaD8w==} + + '@push.rocks/smartrequest@4.4.2': + resolution: {integrity: sha512-Om4y1Ce4YdSu8VoXREz2SgFz9pDxcFEm0+SC1YYa3RXd0AH2Mknaj/1XfvfMqojnK9L7N2z1fY4xX8tO1IwqFQ==} + + '@push.rocks/smartrequest@5.0.1': + resolution: {integrity: sha512-gZQQF6HVt3LwTBxaPh6hHObd4VF76PUYQcs5pHD7f0VXaEewmrNAQSnccoinOY7fi45+0dOf04PJOXu9MibPzQ==} + + '@push.rocks/smartrouter@1.3.3': + resolution: {integrity: sha512-1+xZEnWlhzqLWAaJ1zFNhQ0zgbfCWQl1DBT72LygLxTs+P0K8AwJKgqo/IX6CT55kGCFnPAZIYSbVJlGsgrB0w==} + + '@push.rocks/smartrust@1.3.2': + resolution: {integrity: sha512-HPzSJgDnKUdE5fkn2+BC9JvFXk7wl6aURAiHAXjHSCBLtzfgB7jEXjlg+K6CEfMjwQV7sy+hYABlq5DLXcFseQ==} + + '@push.rocks/smartrx@3.0.10': + resolution: {integrity: sha512-USjIYcsSfzn14cwOsxgq/bBmWDTTzy3ouWAnW5NdMyRRzEbmeNrvmy6TRqNeDlJ2PsYNTt1rr/zGUqvIy72ITg==} + + '@push.rocks/smartserve@2.0.3': + resolution: {integrity: sha512-PttdFlh61lsDNSRvRCSlKjRzuxgD3WP2XLuBNXu1hLfqLpQXDESj0ZCRPDZslLZsyFT5aHP9godb4D4L3bzHWA==} + + '@push.rocks/smartshell@3.3.8': + resolution: {integrity: sha512-t9J/py0vnea4ZtOs7Anc9dc6lcvg6EDvYBw5eE1mB+KUWxMQf/ROIQwWMo6B9SMNY4JS2UwvfuJQJ8makP/7Tg==} + + '@push.rocks/smartspawn@3.0.3': + resolution: {integrity: sha512-DyrGPV69wwOiJgKkyruk5hS3UEGZ99xFAqBE9O2nM8VXCRLbbty3xt1Ug5Z092ZZmJYaaGMSnMw3ijyZJFCT0Q==} + + '@push.rocks/smartstate@2.3.0': + resolution: {integrity: sha512-NfyQYlhYJdVS5XvXEREB7NixaOv0CFuBDMImjN9JtF3dToJvjciBTMhKMGOJ6IKpza39y2zrH+gABapYNfzZ3A==} + + '@push.rocks/smartstorage@6.3.2': + resolution: {integrity: sha512-g8rXlVZ+6iKmzNoybtwQntdb7EWA6WnVmbXNOdwDKWR8w4o/7UMErj+H5mt57iqYIy1pzQAoTb8IWJNsti7XQw==} + + '@push.rocks/smartstream@3.4.0': + resolution: {integrity: sha512-kePb44W9n5K96zj2Ms3K4xnYbNXP5AfxDd86zZMDQ1/T10nvkIpL9m5w4lG/VJ4KAsWFs81S87BkkcjhhrY5Kw==} + + '@push.rocks/smartstring@4.1.0': + resolution: {integrity: sha512-Q4py/Nm3KTDhQ9EiC75yBtSTLR0KLMwhKM+8gGcutgKotZT6wJ3gncjmtD8LKFfNhb4lSaFMgPJgLrCHTOH6Iw==} + + '@push.rocks/smarttime@4.2.3': + resolution: {integrity: sha512-8gMg8RUkrCG4p9NcEUZV7V6KpL24+jAMK02g7qyhfA6giz/JJWD0+8w8xjSR+G7qe16KVQ2y3RbvAL9TxmO36g==} + + '@push.rocks/smartunique@3.0.9': + resolution: {integrity: sha512-q6DYQgT7/dqdWi9HusvtWCjdsFzLFXY9LTtaZV6IYNJt6teZOonoygxTdNt9XLn6niBSbLYrHSKvJNTRH/uK+g==} + + '@push.rocks/smarturl@3.1.0': + resolution: {integrity: sha512-ij73Q4GERojdPSHxAvYKvspimcpAJC6GGQCWsC4b+1sAiOSByjfmkUHK8yiEEOPRU9AeGuyaIVqK6ZzKLEZ3vA==} + + '@push.rocks/smartversion@3.1.0': + resolution: {integrity: sha512-qsJb82p8aQzJQ04fLiZsrxarhn+IoOn6v1B869NjH06vOCbCHXNKoS8WPssE6E6zge4NPCCD5WQ2hkyzqxCv9A==} + + '@push.rocks/smartwatch@6.4.0': + resolution: {integrity: sha512-KDswRgE/siBmZRCsRA07MtW5oF4c9uQEBkwTGPIWneHzksbCDsvs/7agKFEL7WnNifLNwo8w1K1qoiVWkX1fvw==} + engines: {node: '>=20.0.0'} + + '@push.rocks/smartyaml@2.0.5': + resolution: {integrity: sha512-tBcf+HaOIfeEsTMwgUZDtZERCxXQyRsWO8Ar5DjBdiSRchbhVGZQEBzXswMS0W5ZoRenjgPK+4tPW3JQGRTfbg==} + + '@push.rocks/taskbuffer@3.5.0': + resolution: {integrity: sha512-Y9WwIEIyp6oVFdj06j84tfrZIvjhbMb3DF52rYxlTeYLk3W7RPhSg1bGPCbtkXWeKdBrSe37V90BkOG7Qq8Pqg==} + + '@push.rocks/taskbuffer@8.0.2': + resolution: {integrity: sha512-SRCAzrSHysW5XEjwZ494V60ybdpOo/s96jDD3sn7SkYolzg2Pboh+SW5Q7SVNcdkP4b9wCEizOYe9CB3vj3W6w==} + + '@push.rocks/webrequest@4.0.5': + resolution: {integrity: sha512-wVSCaXqJ9Vh+rbwVz0wDl46dYz4rnwwSrm5vbVXKbuH6oKTPF0YRoujeJPqRltIn64RVGdLeY9/6ix+ZCrzhsg==} + + '@push.rocks/websetup@3.0.19': + resolution: {integrity: sha512-iKJDwXdMmQdu5siOIgziPRxM51lN1AU9HOr+yMteu1YMDkZT7HKCyisDAr4gC9WZ9a7FzsG8zgthm4dMeA8NTw==} + + '@push.rocks/webstore@2.0.21': + resolution: {integrity: sha512-vH9TJlVFHL5WP1YsNW+JbRfAcIro3oYbogQmv7jA9yaYnswCxG6HWl7Ca2vcfsoAAB28pyjX8hvRqfD2a5hKNQ==} + + '@push.rocks/webstream@1.0.10': + resolution: {integrity: sha512-45CcR0I4/9v0qSjLvz2dYTGMkR0YP3x66ItpStdad5hidJm86t1lfHF06d0oiEvJTpvQkeyIX/8YKAumf21d/Q==} + + '@pushrocks/smartdelay@3.0.1': + resolution: {integrity: sha512-I+i/QhC6kLsXsWyW19UgD1vH2r1YWVxK19VMxt2CEuvxMyC6tuCd0vqud9vv5JxaxsJwxWlOsrURkgL4tXeILQ==} + deprecated: This package has been deprecated in favour of the new package at @push.rocks/smartdelay + + '@pushrocks/smartpromise@4.0.2': + resolution: {integrity: sha512-bqorOaGXPOuiOSV81luTKrTghg4O4NBRD0zyv7TIqmrMGf4a0uoozaUMp1X8vQdZW+y0gTzUJP9wkzAE6Cci0g==} + deprecated: This package has been deprecated in favour of the new package at @push.rocks/smartpromise + + '@rolldown/binding-android-arm64@1.0.0-rc.11': + resolution: {integrity: sha512-SJ+/g+xNnOh6NqYxD0V3uVN4W3VfnrGsC9/hoglicgTNfABFG9JjISvkkU0dNY84MNHLWyOgxP9v9Y9pX4S7+A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-rc.11': + resolution: {integrity: sha512-7WQgR8SfOPwmDZGFkThUvsmd/nwAWv91oCO4I5LS7RKrssPZmOt7jONN0cW17ydGC1n/+puol1IpoieKqQidmg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-rc.11': + resolution: {integrity: sha512-39Ks6UvIHq4rEogIfQBoBRusj0Q0nPVWIvqmwBLaT6aqQGIakHdESBVOPRRLacy4WwUPIx4ZKzfZ9PMW+IeyUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-rc.11': + resolution: {integrity: sha512-jfsm0ZHfhiqrvWjJAmzsqiIFPz5e7mAoCOPBNTcNgkiid/LaFKiq92+0ojH+nmJmKYkre4t71BWXUZDNp7vsag==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.11': + resolution: {integrity: sha512-zjQaUtSyq1nVe3nxmlSCuR96T1LPlpvmJ0SZy0WJFEsV4kFbXcq2u68L4E6O0XeFj4aex9bEauqjW8UQBeAvfQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.11': + resolution: {integrity: sha512-WMW1yE6IOnehTcFE9eipFkm3XN63zypWlrJQ2iF7NrQ9b2LDRjumFoOGJE8RJJTJCTBAdmLMnJ8uVitACUUo1Q==} + 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==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.11': + resolution: {integrity: sha512-LXk5Hii1Ph9asuGRjBuz8TUxdc1lWzB7nyfdoRgI0WGPZKmCxvlKk8KfYysqtr4MfGElu/f/pEQRh8fcEgkrWw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.11': + resolution: {integrity: sha512-dDwf5otnx0XgRY1yqxOC4ITizcdzS/8cQ3goOWv3jFAo4F+xQYni+hnMuO6+LssHHdJW7+OCVL3CoU4ycnh35Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.11': + resolution: {integrity: sha512-LN4/skhSggybX71ews7dAj6r2geaMJfm3kMbK2KhFMg9B10AZXnKoLCVVgzhMHL0S+aKtr4p8QbAW8k+w95bAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-rc.11': + resolution: {integrity: sha512-xQO9vbwBecJRv9EUcQ/y0dzSTJgA7Q6UVN7xp6B81+tBGSLVAK03yJ9NkJaUA7JFD91kbjxRSC/mDnmvXzbHoQ==} + + '@rspack/binding-darwin-arm64@1.7.11': + resolution: {integrity: sha512-oduECiZVqbO5zlVw+q7Vy65sJFth99fWPTyucwvLJJtJkPL5n17Uiql2cYP6Ijn0pkqtf1SXgK8WjiKLG5bIig==} + cpu: [arm64] + os: [darwin] + + '@rspack/binding-darwin-x64@1.7.11': + resolution: {integrity: sha512-a1+TtTE9ap6RalgFi7FGIgkJP6O4Vy6ctv+9WGJy53E4kuqHR0RygzaiVxCI/GMc/vBT9vY23hyrpWb3d1vtXA==} + cpu: [x64] + os: [darwin] + + '@rspack/binding-linux-arm64-gnu@1.7.11': + resolution: {integrity: sha512-P0QrGRPbTWu6RKWfN0bDtbnEps3rXH0MWIMreZABoUrVmNQKtXR6e73J3ub6a+di5s2+K0M2LJ9Bh2/H4UsDUA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rspack/binding-linux-arm64-musl@1.7.11': + resolution: {integrity: sha512-6ky7R43VMjWwmx3Yx7Jl7faLBBMAgMDt+/bN35RgwjiPgsIByz65EwytUVuW9rikB43BGHvA/eqlnjLrUzNBqw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rspack/binding-linux-x64-gnu@1.7.11': + resolution: {integrity: sha512-cuOJMfCOvb2Wgsry5enXJ3iT1FGUjdPqtGUBVupQlEG4ntSYsQ2PtF4wIDVasR3wdxC5nQbipOrDiN/u6fYsdQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rspack/binding-linux-x64-musl@1.7.11': + resolution: {integrity: sha512-CoK37hva4AmHGh3VCsQXmGr40L36m1/AdnN5LEjUX6kx5rEH7/1nEBN6Ii72pejqDVvk9anEROmPDiPw10tpFg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rspack/binding-wasm32-wasi@1.7.11': + resolution: {integrity: sha512-OtrmnPUVJMxjNa3eDMfHyPdtlLRmmp/aIm0fQHlAOATbZvlGm12q7rhPW5BXTu1yh+1rQ1/uqvz+SzKEZXuJaQ==} + cpu: [wasm32] + + '@rspack/binding-win32-arm64-msvc@1.7.11': + resolution: {integrity: sha512-lObFW6e5lCWNgTBNwT//yiEDbsxm9QG4BYUojqeXxothuzJ/L6ibXz6+gLMvbOvLGV3nKgkXmx8GvT9WDKR0mA==} + cpu: [arm64] + os: [win32] + + '@rspack/binding-win32-ia32-msvc@1.7.11': + resolution: {integrity: sha512-0pYGnZd8PPqNR68zQ8skamqNAXEA1sUfXuAdYcknIIRq2wsbiwFzIc0Pov1cIfHYab37G7sSIPBiOUdOWF5Ivw==} + cpu: [ia32] + os: [win32] + + '@rspack/binding-win32-x64-msvc@1.7.11': + resolution: {integrity: sha512-EeQXayoQk/uBkI3pdoXfQBXNIUrADq56L3s/DFyM2pJeUDrWmhfIw2UFIGkYPTMSCo8F2JcdcGM32FGJrSnU0Q==} + cpu: [x64] + os: [win32] + + '@rspack/binding@1.7.11': + resolution: {integrity: sha512-2MGdy2s2HimsDT444Bp5XnALzNRxuBNc7y0JzyuqKbHBywd4x2NeXyhWXXoxufaCFu5PBc9Qq9jyfjW2Aeh06Q==} + + '@rspack/core@1.7.11': + resolution: {integrity: sha512-rsD9b+Khmot5DwCMiB3cqTQo53ioPG3M/A7BySu8+0+RS7GCxKm+Z+mtsjtG/vsu4Tn2tcqCdZtA3pgLoJB+ew==} + engines: {node: '>=18.12.0'} + peerDependencies: + '@swc/helpers': '>=0.5.1' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@rspack/lite-tapable@1.1.0': + resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==} + + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@sindresorhus/is@5.6.0': + resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} + engines: {node: '>=14.16'} + + '@smithy/chunked-blob-reader-native@4.2.3': + resolution: {integrity: sha512-jA5k5Udn7Y5717L86h4EIv06wIr3xn8GM1qHRi/Nf31annXcXHJjBKvgztnbn2TxH3xWrPBfgwHsOwZf0UmQWw==} + engines: {node: '>=18.0.0'} + + '@smithy/chunked-blob-reader@5.2.2': + resolution: {integrity: sha512-St+kVicSyayWQca+I1rGitaOEH6uKgE8IUWoYnnEX26SWdWQcL6LvMSD19Lg+vYHKdT9B2Zuu7rd3i6Wnyb/iw==} + engines: {node: '>=18.0.0'} + + '@smithy/config-resolver@4.4.14': + resolution: {integrity: sha512-N55f8mPEccpzKetUagdvmAy8oohf0J5cuj9jLI1TaSceRlq0pJsIZepY3kmAXAhyxqXPV6hDerDQhqQPKWgAoQ==} + engines: {node: '>=18.0.0'} + + '@smithy/core@3.23.14': + resolution: {integrity: sha512-vJ0IhpZxZAkFYOegMKSrxw7ujhhT2pass/1UEcZ4kfl5srTAqtPU5I7MdYQoreVas3204ykCiNhY1o7Xlz6Yyg==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.2.13': + resolution: {integrity: sha512-wboCPijzf6RJKLOvnjDAiBxGSmSnGXj35o5ZAWKDaHa/cvQ5U3ZJ13D4tMCE8JG4dxVAZFy/P0x/V9CwwdfULQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-codec@4.2.13': + resolution: {integrity: sha512-vYahwBAtRaAcFbOmE9aLr12z7RiHYDSLcnogSdxfm7kKfsNa3wH+NU5r7vTeB5rKvLsWyPjVX8iH94brP7umiQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-browser@4.2.13': + resolution: {integrity: sha512-wwybfcOX0tLqCcBP378TIU9IqrDuZq/tDV48LlZNydMpCnqnYr+hWBAYbRE+rFFf/p7IkDJySM3bgiMKP2ihPg==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-config-resolver@4.3.13': + resolution: {integrity: sha512-ied1lO559PtAsMJzg2TKRlctLnEi1PfkNeMMpdwXDImk1zV9uvS/Oxoy/vcy9uv1GKZAjDAB5xT6ziE9fzm5wA==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-node@4.2.13': + resolution: {integrity: sha512-hFyK+ORJrxAN3RYoaD6+gsGDQjeix8HOEkosoajvXYZ4VeqonM3G4jd9IIRm/sWGXUKmudkY9KdYjzosUqdM8A==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-universal@4.2.13': + resolution: {integrity: sha512-kRrq4EKLGeOxhC2CBEhRNcu1KSzNJzYY7RK3S7CxMPgB5dRrv55WqQOtRwQxQLC04xqORFLUgnDlc6xrNUULaA==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.3.16': + resolution: {integrity: sha512-nYDRUIvNd4mFmuXraRWt6w5UsZTNqtj4hXJA/iiOD4tuseIdLP9Lq38teH/SZTcIFCa2f+27o7hYpIsWktJKEQ==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-blob-browser@4.2.14': + resolution: {integrity: sha512-rtQ5es8r/5v4rav7q5QTsfx9CtCyzrz/g7ZZZBH2xtMmd6G/KQrLOWfSHTvFOUPlVy59RQvxeBYJaLRoybMEyA==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-node@4.2.13': + resolution: {integrity: sha512-4/oy9h0jjmY80a2gOIo75iLl8TOPhmtx4E2Hz+PfMjvx/vLtGY4TMU/35WRyH2JHPfT5CVB38u4JRow7gnmzJA==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-stream-node@4.2.13': + resolution: {integrity: sha512-WdQ7HwUjINXETeh6dqUeob1UHIYx8kAn9PSp1HhM2WWegiZBYVy2WXIs1lB07SZLan/udys9SBnQGt9MQbDpdg==} + engines: {node: '>=18.0.0'} + + '@smithy/invalid-dependency@4.2.13': + resolution: {integrity: sha512-jvC0RB/8BLj2SMIkY0Npl425IdnxZJxInpZJbu563zIRnVjpDMXevU3VMCRSabaLB0kf/eFIOusdGstrLJ8IDg==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.2.2': + resolution: {integrity: sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==} + engines: {node: '>=18.0.0'} + + '@smithy/md5-js@4.2.13': + resolution: {integrity: sha512-cNm7I9NXolFxtS20ojROddOEpSAeI1Obq6pd1Kj5HtHws3s9Fkk8DdHDfQSs5KuxCewZuVK6UqrJnfJmiMzDuQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.2.13': + resolution: {integrity: sha512-IPMLm/LE4AZwu6qiE8Rr8vJsWhs9AtOdySRXrOM7xnvclp77Tyh7hMs/FRrMf26kgIe67vFJXXOSmVxS7oKeig==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.4.29': + resolution: {integrity: sha512-R9Q/58U+qBiSARGWbAbFLczECg/RmysRksX6Q8BaQEpt75I7LI6WGDZnjuC9GXSGKljEbA7N118LhGaMbfrTXw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.5.0': + resolution: {integrity: sha512-/NzISn4grj/BRFVua/xnQwF+7fakYZgimpw2dfmlPgcqecBMKxpB9g5mLYRrmBD5OrPoODokw4Vi1hrSR4zRyw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.2.17': + resolution: {integrity: sha512-0T2mcaM6v9W1xku86Dk0bEW7aEseG6KenFkPK98XNw0ZhOqOiD1MrMsdnQw9QsL3/Oa85T53iSMlm0SZdSuIEQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.2.13': + resolution: {integrity: sha512-g72jN/sGDLyTanrCLH9fhg3oysO3f7tQa6eWWsMyn2BiYNCgjF24n4/I9wff/5XidFvjj9ilipAoQrurTUrLvw==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.3.13': + resolution: {integrity: sha512-iGxQ04DsKXLckbgnX4ipElrOTk+IHgTyu0q0WssZfYhDm9CQWHmu6cOeI5wmWRxpXbBDhIIfXMWz5tPEtcVqbw==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.5.2': + resolution: {integrity: sha512-/oD7u8M0oj2ZTFw7GkuuHWpIxtWdLlnyNkbrWcyVYhd5RJNDuczdkb0wfnQICyNFrVPlr8YHOhamjNy3zidhmA==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.2.13': + resolution: {integrity: sha512-bGzUCthxRmezuxkbu9wD33wWg9KX3hJpCXpQ93vVkPrHn9ZW6KNNdY5xAUWNuRCwQ+VyboFuWirG1lZhhkcyRQ==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.3.13': + resolution: {integrity: sha512-+HsmuJUF4u8POo6s8/a2Yb/AQ5t/YgLovCuHF9oxbocqv+SZ6gd8lC2duBFiCA/vFHoHQhoq7QjqJqZC6xOxxg==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.2.13': + resolution: {integrity: sha512-tG4aOYFCZdPMjbgfhnIQ322H//ojujldp1SrHPHpBSb3NqgUp3dwiUGRJzie87hS1DYwWGqDuPaowoDF+rYCbQ==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.2.13': + resolution: {integrity: sha512-hqW3Q4P+CDzUyQ87GrboGMeD7XYNMOF+CuTwu936UQRB/zeYn3jys8C3w+wMkDfY7CyyyVwZQ5cNFoG0x1pYmA==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.2.13': + resolution: {integrity: sha512-a0s8XZMfOC/qpqq7RCPvJlk93rWFrElH6O++8WJKz0FqnA4Y7fkNi/0mnGgSH1C4x6MFsuBA8VKu4zxFrMe5Vw==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.4.8': + resolution: {integrity: sha512-VZCZx2bZasxdqxVgEAhREvDSlkatTPnkdWy1+Kiy8w7kYPBosW0V5IeDwzDUMvWBt56zpK658rx1cOBFOYaPaw==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.3.13': + resolution: {integrity: sha512-YpYSyM0vMDwKbHD/JA7bVOF6kToVRpa+FM5ateEVRpsTNu564g1muBlkTubXhSKKYXInhpADF46FPyrZcTLpXg==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.12.9': + resolution: {integrity: sha512-ovaLEcTU5olSeHcRXcxV6viaKtpkHZumn6Ps0yn7dRf2rRSfy794vpjOtrWDO0d1auDSvAqxO+lyhERSXQ03EQ==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.14.0': + resolution: {integrity: sha512-OWgntFLW88kx2qvf/c/67Vno1yuXm/f9M7QFAtVkkO29IJXGBIg0ycEaBTH0kvCtwmvZxRujrgP5a86RvsXJAQ==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.2.13': + resolution: {integrity: sha512-2G03yoboIRZlZze2+PT4GZEjgwQsJjUgn6iTsvxA02bVceHR6vp4Cuk7TUnPFWKF+ffNUk3kj4COwkENS2K3vw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.3.2': + resolution: {integrity: sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.2.2': + resolution: {integrity: sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.2.3': + resolution: {integrity: sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.2.2': + resolution: {integrity: sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-config-provider@4.2.2': + resolution: {integrity: sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.3.45': + resolution: {integrity: sha512-ag9sWc6/nWZAuK3Wm9KlFJUnRkXLrXn33RFjIAmCTFThqLHY+7wCst10BGq56FxslsDrjhSie46c8OULS+BiIw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.2.49': + resolution: {integrity: sha512-jlN6vHwE8gY5AfiFBavtD3QtCX2f7lM3BKkz7nFKSNfFR5nXLXLg6sqXTJEEyDwtxbztIDBQCfjsGVXlIru2lQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.3.4': + resolution: {integrity: sha512-BKoR/ubPp9KNKFxPpg1J28N1+bgu8NGAtJblBP7yHy8yQPBWhIAv9+l92SlQLpolGm71CVO+btB60gTgzT0wog==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@4.2.2': + resolution: {integrity: sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-middleware@4.2.13': + resolution: {integrity: sha512-GTooyrlmRTqvUen4eK7/K1p6kryF7bnDfq6XsAbIsf2mo51B/utaH+XThY6dKgNCWzMAaH/+OLmqaBuLhLWRow==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.3.0': + resolution: {integrity: sha512-tSOPQNT/4KfbvqeMovWC3g23KSYy8czHd3tlN+tOYVNIDLSfxIsrPJihYi5TpNcoV789KWtgChUVedh2y6dDPg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.5.22': + resolution: {integrity: sha512-3H8iq/0BfQjUs2/4fbHZ9aG9yNzcuZs24LPkcX1Q7Z+qpqaGM8+qbGmE8zo9m2nCRgamyvS98cHdcWvR6YUsew==} + engines: {node: '>=18.0.0'} + + '@smithy/util-uri-escape@4.2.2': + resolution: {integrity: sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.2.2': + resolution: {integrity: sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-waiter@4.2.15': + resolution: {integrity: sha512-oUt9o7n8hBv3BL56sLSneL0XeigZSuem0Hr78JaoK33D9oKieyCvVP8eTSe3j7g2mm/S1DvzxKieG7JEWNJUNg==} + engines: {node: '>=18.0.0'} + + '@smithy/uuid@1.1.2': + resolution: {integrity: sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==} + engines: {node: '>=18.0.0'} + + '@szmarczak/http-timer@5.0.1': + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} + + '@tempfix/lenis@1.3.20': + resolution: {integrity: sha512-ypeB0FuHLHOCQXW4d0RQ69txPJJH+1CHcpsZIUdcv2t1vR0IVyQr2vHihtde9UOXhjzqEnUphWon/UcJNsa0YA==} + peerDependencies: + '@nuxt/kit': '>=3.0.0' + react: '>=17.0.0' + vue: '>=3.0.0' + peerDependenciesMeta: + '@nuxt/kit': + optional: true + react: + optional: true + vue: + optional: true + + '@tokenizer/inflate@0.4.1': + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} + engines: {node: '>=18'} + + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + + '@tsclass/tsclass@4.4.4': + resolution: {integrity: sha512-YZOAF+u+r4u5rCev2uUd1KBTBdfyFdtDmcv4wuN+864lMccbdfRICR3SlJwCfYS1lbeV3QNLYGD30wjRXgvCJA==} + + '@tsclass/tsclass@9.5.0': + resolution: {integrity: sha512-HwMVwkrBnEFMjwOsMkGwWN/q+XEczSpf4a/PBAXgkDdV6sXdxAMFXUH1tW8Y5ecuvXFYMvFry4X57MCCT7Dm8A==} + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/clean-css@4.2.11': + resolution: {integrity: sha512-Y8n81lQVTAfP2TOdtJJEsCoYl1AnOkqDqMvXb9/7pfgZZ7r8YrEyurrAvAoAjHOGXKRybay+5CsExqIH6liccw==} + + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/html-minifier@4.0.6': + resolution: {integrity: sha512-1Dcf38DkVMYo8SIOkUka7GxI+0BztCVsnfiG2Sxb6G8ShHDQTWQb1WKps/eb3O074HNDCn8wU7LMl5N99nNG+Q==} + + '@types/http-cache-semantics@4.2.0': + resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} + + '@types/js-yaml@3.12.10': + resolution: {integrity: sha512-/Mtaq/wf+HxXpvhzFYzrzCqNRcA958sW++7JOFC8nPrZcvfi/TrzOaaGbvt27ltJB2NQbHVAg5a1wUCsyMH7NA==} + + '@types/js-yaml@4.0.9': + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + + '@types/jsonfile@6.1.4': + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mime-types@2.1.4': + resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/mute-stream@0.0.4': + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + + '@types/node-forge@1.3.14': + resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==} + + '@types/node@16.9.1': + resolution: {integrity: sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==} + + '@types/node@22.19.17': + resolution: {integrity: sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==} + + '@types/node@25.5.2': + resolution: {integrity: sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==} + + '@types/relateurl@0.2.33': + resolution: {integrity: sha512-bTQCKsVbIdzLqZhLkF5fcJQreE4y1ro4DIyVrlDNSCJRRwHhB8Z+4zXXa8jN6eDvc2HbRsEYgbvrnGvi54EpSw==} + + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + + '@types/tar-stream@3.1.4': + resolution: {integrity: sha512-921gW0+g29mCJX0fRvqeHzBlE/XclDaAG0Ousy1LCghsOhvaKacDeRGEVzQP9IPfKn8Vysy7FEXAIxycpc/CMg==} + + '@types/through2@2.0.41': + resolution: {integrity: sha512-ryQ0tidWkb1O1JuYvWKyMLYEtOWDqF5mHerJzKz/gQpoAaJq2l/dsMPBF0B5BNVT34rbARYJ5/tsZwLfUi2kwQ==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@types/turndown@5.0.6': + resolution: {integrity: sha512-ru00MoyeeouE5BX4gRL+6m/BsDfbRayOskWqUvh7CLGW+UXxHQItqALa38kKnOiZPqJrtzJUgAC2+F0rL1S4Pg==} + + '@types/uglify-js@3.17.5': + resolution: {integrity: sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/uuid@9.0.8': + resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} + + '@types/webidl-conversions@7.0.3': + resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} + + '@types/whatwg-url@11.0.5': + resolution: {integrity: sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==} + + '@types/whatwg-url@13.0.0': + resolution: {integrity: sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==} + + '@types/which@3.0.4': + resolution: {integrity: sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==} + + '@types/wrap-ansi@3.0.0': + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + acme-client@5.4.0: + resolution: {integrity: sha512-mORqg60S8iML6XSmVjqjGHJkINrCGLMj2QvDmFzI9vIlv1RGlyjmw3nrzaINJjkNsYXC41XhhD5pfy7CtuGcbA==} + engines: {node: '>= 16'} + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + ansi-256-colors@1.1.0: + resolution: {integrity: sha1-kQ3lDvzHwJ49gvL4er1rcAwYgYo=} + engines: {node: '>=0.10.0'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + any-base@1.1.0: + resolution: {integrity: sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + asn1js@3.0.7: + resolution: {integrity: sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==} + engines: {node: '>=12.0.0'} + + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + + async-mutex@0.5.0: + resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==} + + asynckit@0.4.0: + resolution: {integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=} + + await-to-js@3.0.0: + resolution: {integrity: sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==} + engines: {node: '>=6.0.0'} + + axios@1.14.0: + resolution: {integrity: sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==} + + b4a@1.8.0: + resolution: {integrity: sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==} + peerDependencies: + react-native-b4a: '*' + peerDependenciesMeta: + react-native-b4a: + optional: true + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + 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: + bare-abort-controller: '*' + peerDependenciesMeta: + bare-abort-controller: + optional: true + + bare-fs@4.6.0: + resolution: {integrity: sha512-2YkS7NuiJceSEbyEOdSNLE9tsGd+f4+f7C+Nik/MCk27SYdwIMPT/yRKvg++FZhQXgk0KWJKJyXX9RhVV0RGqA==} + engines: {bare: '>=1.16.0'} + peerDependencies: + bare-buffer: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + + bare-os@3.8.7: + resolution: {integrity: sha512-G4Gr1UsGeEy2qtDTZwL7JFLo2wapUarz7iTMcYcMFdS89AIQuBoyjgXZz0Utv7uHs3xA9LckhVbeBi8lEQrC+w==} + engines: {bare: '>=1.14.0'} + + bare-path@3.0.0: + resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} + + bare-stream@2.12.0: + resolution: {integrity: sha512-w28i8lkBgREV3rPXGbgK+BO66q+ZpKqRWrZLiCdmmUlLPrQ45CzkvRhN+7lnv00Gpi2zy5naRxnUFAxCECDm9g==} + peerDependencies: + bare-abort-controller: '*' + bare-buffer: '*' + bare-events: '*' + peerDependenciesMeta: + bare-abort-controller: + optional: true + bare-buffer: + optional: true + bare-events: + optional: true + + bare-url@2.4.0: + resolution: {integrity: sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + basic-ftp@5.2.0: + resolution: {integrity: sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==} + engines: {node: '>=10.0.0'} + + bmp-ts@1.0.9: + resolution: {integrity: sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==} + + bowser@2.14.1: + resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} + + brace-expansion@1.1.13: + resolution: {integrity: sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==} + + brace-expansion@2.0.3: + resolution: {integrity: sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==} + + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + engines: {node: 18 || 20 || >=22} + + broadcast-channel@7.3.0: + resolution: {integrity: sha512-UHPhLBQKfQ8OmMFMpmPfO5dRakyA1vsfiDGWTYNvChYol65tbuhivPEGgZZiuetorvExdvxaWiBy/ym1Ty08yA==} + + bson@6.10.4: + resolution: {integrity: sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==} + engines: {node: '>=16.20.1'} + + bson@7.2.0: + resolution: {integrity: sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==} + engines: {node: '>=20.19.0'} + + buffer-crc32@0.2.13: + resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} + + cacheable-request@10.2.14: + resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} + engines: {node: '>=14.16'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@3.0.0: + resolution: {integrity: sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + chromium-bidi@14.0.0: + resolution: {integrity: sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw==} + peerDependencies: + devtools-protocol: '*' + + clean-css@4.2.4: + resolution: {integrity: sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==} + engines: {node: '>= 4.0'} + + clean-stack@1.3.0: + resolution: {integrity: sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=} + engines: {node: '>=4'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commondir@1.0.1: + resolution: {integrity: sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=} + + concat-map@0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + cosmiconfig@9.0.1: + resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + croner@10.0.1: + resolution: {integrity: sha512-ixNtAJndqh173VQ4KodSdJEI6nuioBWI0V1ITNKhZZsO0pEMoDxz539T4FTTbSZ/xIOSuDnzxLVRqBVSvPNE2g==} + engines: {node: '>=18.0'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + + date-fns@4.1.0: + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + + dayjs@1.11.20: + resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.3.0: + resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + + delayed-stream@1.0.0: + resolution: {integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk=} + engines: {node: '>=0.4.0'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + devtools-protocol@0.0.1581282: + resolution: {integrity: sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + esm@3.2.25: + resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} + engines: {node: '>=6'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + events-universal@1.0.1: + resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + exif-parser@0.1.12: + resolution: {integrity: sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + + fake-indexeddb@6.2.5: + resolution: {integrity: sha512-CGnyrvbhPlWYMngksqrSSUT1BAVP49dZocrHuK0SvtR0D5TMs5wP0o3j7jexDJW01KSadjBp1M/71o/KR3nD1w==} + engines: {node: '>=18'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-xml-builder@1.1.4: + resolution: {integrity: sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==} + + fast-xml-parser@5.5.8: + resolution: {integrity: sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==} + hasBin: true + + fault@2.0.1: + resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} + + fd-slicer@1.1.0: + resolution: {integrity: sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=} + + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-type@16.5.4: + resolution: {integrity: sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==} + engines: {node: '>=10'} + + file-type@19.6.0: + resolution: {integrity: sha512-VZR5I7k5wkD0HgFnMsq5hOsSc710MJMu5Nc5QYsbe38NN5iPV/XTObYLc/cpttRTf6lX538+5uO1ZQRhYibiZQ==} + engines: {node: '>=18'} + + file-type@21.3.4: + resolution: {integrity: sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==} + engines: {node: '>=20'} + + find-cache-dir@3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + foreground-child@2.0.0: + resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} + engines: {node: '>=8.0.0'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data-encoder@2.1.4: + resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} + engines: {node: '>= 14.17'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + format@0.2.2: + resolution: {integrity: sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=} + engines: {node: '>=0.4.x'} + + fs-extra@11.3.4: + resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} + engines: {node: '>=14.14'} + + fs.realpath@1.0.0: + resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + + get-tsconfig@4.13.7: + resolution: {integrity: sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==} + + get-uri@6.0.5: + resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} + engines: {node: '>= 14'} + + gifwrap@0.10.1: + resolution: {integrity: sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==} + + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + got@12.6.1: + resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} + engines: {node: '>=14.16'} + + graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hast-util-sanitize@5.0.2: + resolution: {integrity: sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg==} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + html-minifier@4.0.0: + resolution: {integrity: sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==} + engines: {node: '>=6'} + hasBin: true + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + http-cache-semantics@4.2.0: + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} + engines: {node: '>=10.19.0'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + humanize-ms@1.2.1: + resolution: {integrity: sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + idb@8.0.3: + resolution: {integrity: sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + image-q@4.0.0: + resolution: {integrity: sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + inflight@1.0.6: + resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + inquirer@11.1.0: + resolution: {integrity: sha512-CmLAZT65GG/v30c+D2Fk8+ceP6pxD6RL+hIUOWAltCmeyEqWYwqu9v76q03OvjyZ3AB0C1Ala2stn1z/rMqGEw==} + engines: {node: '>=18'} + + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} + + is-arrayish@0.2.1: + resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + + is-observable@2.1.0: + resolution: {integrity: sha512-DailKdLb0WU+xX8K5w7VsJhapwHLZ9jjmazqCJq4X12CTgqq73TKnbRcnSLuXYPOoLQgV5IrD7ePiX/h1vnkBw==} + engines: {node: '>=8'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + isexe@2.0.0: + resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} + + isexe@4.0.0: + resolution: {integrity: sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==} + engines: {node: '>=20'} + + jackspeak@4.2.3: + resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} + engines: {node: 20 || >=22} + + jimp@1.6.0: + resolution: {integrity: sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==} + engines: {node: '>=18'} + + jpeg-js@0.4.4: + resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + 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==} + + jsonfile@6.2.0: + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lit-element@4.2.2: + resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} + + lit-html@3.3.2: + resolution: {integrity: sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==} + + lit@3.3.2: + resolution: {integrity: sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + lodash.clonedeep@4.5.0: + resolution: {integrity: sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + lower-case@1.1.4: + resolution: {integrity: sha1-miyr0bno4K6ZOkv31YdcOcQujqw=} + + lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lru-cache@11.3.2: + resolution: {integrity: sha512-wgWa6FWQ3QRRJbIjbsldRJZxdxYngT/dO0I5Ynmlnin8qy7tC6xYzbcJjtN4wHLXtkbVwHzk0C+OejVw1XM+DQ==} + engines: {node: 20 || >=22} + + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + + make-error-cause@2.3.0: + resolution: {integrity: sha512-etgt+n4LlOkGSJbBTV9VROHA5R7ekIPS4vfh+bCAoJgRrJWdqJCBbpS3osRJ/HrT7R68MzMiY3L3sDJ/Fd8aBg==} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + + matcher@5.0.0: + resolution: {integrity: sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + maxmind@5.0.6: + resolution: {integrity: sha512-5bvd/u+kIaTqaGM+xkXjatzQw1dQfSmlLggr2W1EKMyMxSgx2woZyusLpNpZ4DdPmL+1bbJWeo4LXsi6bC0Iew==} + engines: {node: '>=12', npm: '>=6'} + + mdast-util-find-and-replace@3.0.2: + resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} + + mdast-util-from-markdown@2.0.3: + resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==} + + mdast-util-frontmatter@2.0.1: + resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==} + + mdast-util-gfm-autolink-literal@2.0.1: + resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} + + mdast-util-gfm-footnote@2.1.0: + resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} + + mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + + mdast-util-gfm@3.1.0: + resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + memory-pager@1.5.0: + resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} + + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + + micromark-extension-frontmatter@2.0.0: + resolution: {integrity: sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==} + + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} + + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} + + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} + + micromark-extension-gfm-table@2.1.1: + resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} + + micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} + + micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + + mime@4.1.0: + resolution: {integrity: sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==} + engines: {node: '>=16'} + hasBin: true + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + mingo@7.2.1: + resolution: {integrity: sha512-MEIQPOSJS2sVCueyQeE2rzgEeW3HpIIhizPbeuwD4v7+miVj7NI3ZVPqqw8t3YPIWCivpIaXA4KsoRI7koyNOA==} + + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + 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==} + + mongodb-connection-string-url@7.0.1: + resolution: {integrity: sha512-h0AZ9A7IDVwwHyMxmdMXKy+9oNlF0zFoahHiX3vQ8e3KFcSP3VmsmfvtRSuLPxmyv2vjIDxqty8smTgie/SNRQ==} + engines: {node: '>=20.19.0'} + + mongodb-memory-server-core@11.0.1: + resolution: {integrity: sha512-IcIb2S9Xf7Lmz43Z1ZujMqNg7PU5Q7yn+4wOnu7l6pfeGPkEmlqzV1hIbroVx8s4vXhPB1oMGC1u8clW7aj3Xw==} + engines: {node: '>=20.19.0'} + + mongodb-memory-server@11.0.1: + resolution: {integrity: sha512-nUlKovSJZBh7q5hPsewFRam9H66D08Ne18nyknkNalfXMPtK1Og3kOcuqQhcX88x/pghSZPIJHrLbxNFW3OWiw==} + engines: {node: '>=20.19.0'} + + mongodb@6.21.0: + resolution: {integrity: sha512-URyb/VXMjJ4da46OeSXg+puO39XH9DeQpWCslifrRn9JWugy0D+DvvBvkm2WxmHe61O/H19JM66p1z7RHVkZ6A==} + engines: {node: '>=16.20.1'} + peerDependencies: + '@aws-sdk/credential-providers': ^3.188.0 + '@mongodb-js/zstd': ^1.1.0 || ^2.0.0 + gcp-metadata: ^5.2.0 + kerberos: ^2.0.1 + mongodb-client-encryption: '>=6.0.0 <7' + snappy: ^7.3.2 + socks: ^2.7.1 + peerDependenciesMeta: + '@aws-sdk/credential-providers': + optional: true + '@mongodb-js/zstd': + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + snappy: + optional: true + socks: + optional: true + + mongodb@7.1.1: + resolution: {integrity: sha512-067DXiMjcpYQl6bGjWQoTUEE9UoRViTtKFcoqX7z08I+iDZv/emH1g8XEFiO3qiDfXAheT5ozl1VffDTKhIW/w==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@aws-sdk/credential-providers': ^3.806.0 + '@mongodb-js/zstd': ^7.0.0 + gcp-metadata: ^7.0.1 + kerberos: ^7.0.0 + mongodb-client-encryption: '>=7.0.0 <7.1.0' + snappy: ^7.3.2 + socks: ^2.8.6 + peerDependenciesMeta: + '@aws-sdk/credential-providers': + optional: true + '@mongodb-js/zstd': + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + snappy: + optional: true + socks: + optional: true + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + nanoid@4.0.2: + resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} + engines: {node: ^14 || ^16 || >=18} + hasBin: true + + netmask@2.1.0: + resolution: {integrity: sha512-z9sZrk6wyf8/NDKKqe+Tyl58XtgkYrV4kgt1O8xrzYvpl1LvPacPo0imMLHfpStk3kgCIq1ksJ2bmJn9hue2lQ==} + engines: {node: '>= 0.4.0'} + + new-find-package-json@2.0.0: + resolution: {integrity: sha512-lDcBsjBSMlj3LXH2v/FW3txlh2pYTjmbOXPYJD93HI5EwuLzI11tdHSIpUMmfq/IOsldj4Ps8M8flhm+pCK4Ew==} + engines: {node: '>=12.22.0'} + + no-case@2.3.2: + resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} + + node-forge@1.4.0: + resolution: {integrity: sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==} + engines: {node: '>= 6.13.0'} + + normalize-url@8.1.1: + resolution: {integrity: sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==} + engines: {node: '>=14.16'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + oblivious-set@2.0.0: + resolution: {integrity: sha512-QOUH5Xrsced9fKXaQTjWoDGKeS/Or7E2jB0FN63N4mkAO4qJdB7WR7e6qWAOHM5nk25FJ8TGjhP7DH4l6vFVLg==} + engines: {node: '>=16'} + + observable-fns@0.6.1: + resolution: {integrity: sha512-9gRK4+sRWzeN6AOewNBTLXir7Zl/i3GB6Yl26gK4flxz8BXVpD3kt8amREmWNb0mxYOGDotvE5a4N+PtGGKdkg==} + + omggif@1.0.10: + resolution: {integrity: sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==} + + once@1.4.0: + resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} + + os-tmpdir@1.0.2: + resolution: {integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=} + engines: {node: '>=0.10.0'} + + p-cancelable@3.0.0: + resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} + engines: {node: '>=12.20'} + + p-finally@1.0.0: + resolution: {integrity: sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=} + engines: {node: '>=4'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-queue@6.6.2: + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} + + p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + pac-proxy-agent@7.2.0: + resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + package-json@8.1.1: + resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} + engines: {node: '>=14.16'} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + param-case@2.1.1: + resolution: {integrity: sha1-35T9jPZTHs915r75oIWPvHK+Ikc=} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-bmfont-ascii@1.0.6: + resolution: {integrity: sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==} + + parse-bmfont-binary@1.0.6: + resolution: {integrity: sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==} + + parse-bmfont-xml@1.1.6: + resolution: {integrity: sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-expression-matcher@1.4.0: + resolution: {integrity: sha512-s4DQMxIdhj3jLFWd9LxHOplj4p9yQ4ffMGowFf3cpEgrrJjEhN0V5nxw4Ye1EViAGDoL4/1AeO6qHpqYPOzE4Q==} + engines: {node: '>=14.0.0'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + + pdf-lib@1.17.1: + resolution: {integrity: sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==} + + pdf2json@4.0.2: + resolution: {integrity: sha512-iiRSuRmLihoEJ4YGkoqSq3/r4MR0OmkMTYDda0Pq7DAWqJwMylTilXu46T16gfS3DUp3fhiVuz7NtRMbk3uBhw==} + engines: {node: '>=20.18.0'} + hasBin: true + bundledDependencies: [] + + peek-readable@4.1.0: + resolution: {integrity: sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==} + engines: {node: '>=8'} + + peek-readable@5.4.2: + resolution: {integrity: sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg==} + engines: {node: '>=14.16'} + + pend@1.2.0: + resolution: {integrity: sha1-elfrVQpng/kRUzH89GY9XI4AelA=} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + pixelmatch@5.3.0: + resolution: {integrity: sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==} + hasBin: true + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + pngjs@6.0.0: + resolution: {integrity: sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==} + engines: {node: '>=12.13.0'} + + pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} + engines: {node: '>=14.19.0'} + + pretty-ms@9.3.0: + resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} + engines: {node: '>=18'} + + process@0.11.10: + resolution: {integrity: sha1-czIwDoQBYb2j5podHZGn1LwW8YI=} + engines: {node: '>= 0.6.0'} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + + proto-list@1.2.4: + resolution: {integrity: sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=} + + proxy-agent@6.5.0: + resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} + engines: {node: '>= 14'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + puppeteer-core@24.40.0: + resolution: {integrity: sha512-MWL3XbUCfVgGR0gRsidzT6oKJT2QydPLhMITU6HoVWiiv4gkb6gJi3pcdAa8q4HwjBTbqISOWVP4aJiiyUJvag==} + engines: {node: '>=18'} + + puppeteer@24.40.0: + resolution: {integrity: sha512-IxQbDq93XHVVLWHrAkFP7F7iHvb9o0mgfsSIMlhHb+JM+JjM1V4v4MNSQfcRWJopx9dsNOr9adYv0U5fm9BJBQ==} + engines: {node: '>=18'} + hasBin: true + + pvtsutils@1.3.6: + resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} + + pvutils@1.1.5: + resolution: {integrity: sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==} + engines: {node: '>=16.0.0'} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + readable-web-to-node-stream@3.0.4: + resolution: {integrity: sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==} + engines: {node: '>=8'} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + registry-auth-token@5.1.1: + resolution: {integrity: sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==} + engines: {node: '>=14'} + + registry-url@6.0.1: + resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} + engines: {node: '>=12'} + + relateurl@0.2.7: + resolution: {integrity: sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=} + engines: {node: '>= 0.10'} + + remark-frontmatter@5.0.0: + resolution: {integrity: sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==} + + remark-gfm@4.0.1: + resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} + + remark-html@16.0.1: + resolution: {integrity: sha512-B9JqA5i0qZe0Nsf49q3OXyGvyXuZFDzAP2iOFLEumymuYJITVpiH1IgsTEwTpdptDmZlMDMWeDmSawdaJIGCXQ==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + require-directory@2.1.1: + resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=} + engines: {node: '>=0.10.0'} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + responselike@3.0.0: + resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} + engines: {node: '>=14.16'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + + rolldown@1.0.0-rc.11: + resolution: {integrity: sha512-NRjoKMusSjfRbSYiH3VSumlkgFe7kYAa3pzVOsVYVFY3zb5d7nS+a3KGQ7hJKXuYWbzJKPVQ9Wxq2UvyK+ENpw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + run-async@3.0.0: + resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} + engines: {node: '>=0.12.0'} + + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.6.0: + resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + engines: {node: '>=11.0.0'} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-xml-to-json@1.2.7: + resolution: {integrity: sha512-mz9VXphOxQWX3eQ/uXCtm6upltoN0DLx8Zb5T4TFC4FHB7S9FDPGre8CfLWqPWQQH/GrQYd2AXhhVM5LDpYx6Q==} + engines: {node: '>=20.12.2'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@8.0.5: + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} + + socks@2.8.7: + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + sparse-bitfield@3.0.3: + resolution: {integrity: sha1-/0rm5oZWBWuks+eSqzM004JzyhE=} + + spawn-wrap@2.0.0: + resolution: {integrity: sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==} + engines: {node: '>=8'} + + sprintf-js@1.0.3: + resolution: {integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=} + + streamx@2.25.0: + resolution: {integrity: sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo=} + engines: {node: '>=0.10.0'} + + strnum@2.2.3: + resolution: {integrity: sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==} + + strtok3@10.3.5: + resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} + engines: {node: '>=18'} + + strtok3@6.3.0: + resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==} + engines: {node: '>=10'} + + strtok3@9.1.1: + resolution: {integrity: sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw==} + engines: {node: '>=16'} + + sweet-scroll@4.0.0: + resolution: {integrity: sha512-mR6fRsAQANtm3zpzhUE73KAOt2aT4ZsWzNSggiEsSqdO6Zh4gM7ioJG81EngrZEl0XAc3ZvzEfhxggOoEBc8jA==} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + + tar-fs@3.1.2: + resolution: {integrity: sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw==} + + tar-stream@3.1.8: + resolution: {integrity: sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ==} + + teex@1.0.1: + resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} + + text-decoder@1.2.7: + resolution: {integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==} + + threads@1.7.0: + resolution: {integrity: sha512-Mx5NBSHX3sQYR6iI9VYbgHKBLisyB+xROCBGjjWm1O9wb9vfLxdaGtmT/KCjUqMsSNW6nERzCW3T6H43LqjDZQ==} + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + + tiny-lru@13.0.0: + resolution: {integrity: sha512-xDHxKKS1FdF0Tv2P+QT7IeSEg74K/8cEDzbv3Tv6UyHHUgBOjOiQiBp818MGj66dhurQus/IBcoAbwIKtSGc6Q==} + engines: {node: '>=14'} + + tiny-worker@2.3.0: + resolution: {integrity: sha512-pJ70wq5EAqTAEl9IkGzA+fN0836rycEuz2Cn6yeZ6FRzlVS5IDOkFHpIoEsksPRQV34GDqXm65+OlnZqUSyK2g==} + + tinycolor2@1.6.0: + resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + token-types@4.2.1: + resolution: {integrity: sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==} + engines: {node: '>=10'} + + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} + engines: {node: '>=14.16'} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + engines: {node: '>=18.0.0'} + hasBin: true + + tsyringe@4.10.0: + resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==} + engines: {node: '>= 6.0.0'} + + turndown-plugin-gfm@1.0.2: + resolution: {integrity: sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==} + + turndown@7.2.4: + resolution: {integrity: sha512-I8yFsfRzmzK0WV1pNNOA4A7y4RDfFxPRxb3t+e3ui14qSGOxGtiSP6GjeX+Y6CHb7HYaFj7ECUD7VE5kQMZWGQ==} + engines: {node: '>=18', npm: '>=9'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + type-fest@5.5.0: + resolution: {integrity: sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==} + engines: {node: '>=20'} + + typed-query-selector@2.12.1: + resolution: {integrity: sha512-uzR+FzI8qrUEIu96oaeBJmd9E7CFEiQ3goA5qCVgc4s5llSubcfGHq9yUstZx/k4s9dXHVKsE35YWoFyvEqEHA==} + + typescript@6.0.2: + resolution: {integrity: sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==} + engines: {node: '>=14.17'} + hasBin: true + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unload@2.4.1: + resolution: {integrity: sha512-IViSAm8Z3sRBYA+9wc0fLQmU9Nrxb16rcDmIiR6Y9LJSZzI7QY5QsDhqPpKOjAn0O9/kfK1TfNEMMAGPTIraPw==} + + upper-case@1.1.3: + resolution: {integrity: sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=} + + utif2@4.1.0: + resolution: {integrity: sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==} + + util-deprecate@1.0.2: + resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + webdriver-bidi-protocol@0.4.1: + resolution: {integrity: sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@6.0.1: + resolution: {integrity: sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==} + engines: {node: ^20.17.0 || >=22.9.0} + hasBin: true + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrappy@1.0.2: + resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} + + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-parse-from-string@1.0.1: + resolution: {integrity: sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==} + + xml2js@0.5.0: + resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} + engines: {node: '>=4.0.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yauzl@2.10.0: + resolution: {integrity: sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=} + + yauzl@3.3.0: + resolution: {integrity: sha512-PtGEvEP30p7sbIBJKUBjUnqgTVOyMURc4dLo9iNyAJnNIEz9pm88cCXF21w94Kg3k6RXkeZh5DHOGS0qEONvNQ==} + engines: {node: '>=12'} + + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@api.global/typedrequest-interfaces@2.0.2': {} + + '@api.global/typedrequest-interfaces@3.0.19': {} + + '@api.global/typedrequest@3.3.0': + dependencies: + '@api.global/typedrequest-interfaces': 3.0.19 + '@push.rocks/isounique': 1.0.5 + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartbuffer': 3.0.5 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartguard': 3.1.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/webrequest': 4.0.5 + '@push.rocks/webstream': 1.0.10 + + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.6 + tslib: 2.8.1 + + '@aws-crypto/crc32c@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.6 + tslib: 2.8.1 + + '@aws-crypto/sha1-browser@5.2.0': + dependencies: + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.6 + '@aws-sdk/util-locate-window': 3.965.5 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.6 + '@aws-sdk/util-locate-window': 3.965.5 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.6 + tslib: 2.8.1 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.8.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.973.6 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/client-s3@3.1025.0': + dependencies: + '@aws-crypto/sha1-browser': 5.2.0 + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.973.26 + '@aws-sdk/credential-provider-node': 3.972.29 + '@aws-sdk/middleware-bucket-endpoint': 3.972.8 + '@aws-sdk/middleware-expect-continue': 3.972.8 + '@aws-sdk/middleware-flexible-checksums': 3.974.6 + '@aws-sdk/middleware-host-header': 3.972.8 + '@aws-sdk/middleware-location-constraint': 3.972.8 + '@aws-sdk/middleware-logger': 3.972.8 + '@aws-sdk/middleware-recursion-detection': 3.972.9 + '@aws-sdk/middleware-sdk-s3': 3.972.27 + '@aws-sdk/middleware-ssec': 3.972.8 + '@aws-sdk/middleware-user-agent': 3.972.28 + '@aws-sdk/region-config-resolver': 3.972.10 + '@aws-sdk/signature-v4-multi-region': 3.996.15 + '@aws-sdk/types': 3.973.6 + '@aws-sdk/util-endpoints': 3.996.5 + '@aws-sdk/util-user-agent-browser': 3.972.8 + '@aws-sdk/util-user-agent-node': 3.973.14 + '@smithy/config-resolver': 4.4.14 + '@smithy/core': 3.23.14 + '@smithy/eventstream-serde-browser': 4.2.13 + '@smithy/eventstream-serde-config-resolver': 4.3.13 + '@smithy/eventstream-serde-node': 4.2.13 + '@smithy/fetch-http-handler': 5.3.16 + '@smithy/hash-blob-browser': 4.2.14 + '@smithy/hash-node': 4.2.13 + '@smithy/hash-stream-node': 4.2.13 + '@smithy/invalid-dependency': 4.2.13 + '@smithy/md5-js': 4.2.13 + '@smithy/middleware-content-length': 4.2.13 + '@smithy/middleware-endpoint': 4.4.29 + '@smithy/middleware-retry': 4.5.0 + '@smithy/middleware-serde': 4.2.17 + '@smithy/middleware-stack': 4.2.13 + '@smithy/node-config-provider': 4.3.13 + '@smithy/node-http-handler': 4.5.2 + '@smithy/protocol-http': 5.3.13 + '@smithy/smithy-client': 4.12.9 + '@smithy/types': 4.14.0 + '@smithy/url-parser': 4.2.13 + '@smithy/util-base64': 4.3.2 + '@smithy/util-body-length-browser': 4.2.2 + '@smithy/util-body-length-node': 4.2.3 + '@smithy/util-defaults-mode-browser': 4.3.45 + '@smithy/util-defaults-mode-node': 4.2.49 + '@smithy/util-endpoints': 3.3.4 + '@smithy/util-middleware': 4.2.13 + '@smithy/util-retry': 4.3.0 + '@smithy/util-stream': 4.5.22 + '@smithy/util-utf8': 4.2.2 + '@smithy/util-waiter': 4.2.15 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.973.26': + dependencies: + '@aws-sdk/types': 3.973.6 + '@aws-sdk/xml-builder': 3.972.16 + '@smithy/core': 3.23.14 + '@smithy/node-config-provider': 4.3.13 + '@smithy/property-provider': 4.2.13 + '@smithy/protocol-http': 5.3.13 + '@smithy/signature-v4': 5.3.13 + '@smithy/smithy-client': 4.12.9 + '@smithy/types': 4.14.0 + '@smithy/util-base64': 4.3.2 + '@smithy/util-middleware': 4.2.13 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@aws-sdk/crc64-nvme@3.972.5': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.24': + dependencies: + '@aws-sdk/core': 3.973.26 + '@aws-sdk/types': 3.973.6 + '@smithy/property-provider': 4.2.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.26': + dependencies: + '@aws-sdk/core': 3.973.26 + '@aws-sdk/types': 3.973.6 + '@smithy/fetch-http-handler': 5.3.16 + '@smithy/node-http-handler': 4.5.2 + '@smithy/property-provider': 4.2.13 + '@smithy/protocol-http': 5.3.13 + '@smithy/smithy-client': 4.12.9 + '@smithy/types': 4.14.0 + '@smithy/util-stream': 4.5.22 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.972.28': + dependencies: + '@aws-sdk/core': 3.973.26 + '@aws-sdk/credential-provider-env': 3.972.24 + '@aws-sdk/credential-provider-http': 3.972.26 + '@aws-sdk/credential-provider-login': 3.972.28 + '@aws-sdk/credential-provider-process': 3.972.24 + '@aws-sdk/credential-provider-sso': 3.972.28 + '@aws-sdk/credential-provider-web-identity': 3.972.28 + '@aws-sdk/nested-clients': 3.996.18 + '@aws-sdk/types': 3.973.6 + '@smithy/credential-provider-imds': 4.2.13 + '@smithy/property-provider': 4.2.13 + '@smithy/shared-ini-file-loader': 4.4.8 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-login@3.972.28': + dependencies: + '@aws-sdk/core': 3.973.26 + '@aws-sdk/nested-clients': 3.996.18 + '@aws-sdk/types': 3.973.6 + '@smithy/property-provider': 4.2.13 + '@smithy/protocol-http': 5.3.13 + '@smithy/shared-ini-file-loader': 4.4.8 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.972.29': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.24 + '@aws-sdk/credential-provider-http': 3.972.26 + '@aws-sdk/credential-provider-ini': 3.972.28 + '@aws-sdk/credential-provider-process': 3.972.24 + '@aws-sdk/credential-provider-sso': 3.972.28 + '@aws-sdk/credential-provider-web-identity': 3.972.28 + '@aws-sdk/types': 3.973.6 + '@smithy/credential-provider-imds': 4.2.13 + '@smithy/property-provider': 4.2.13 + '@smithy/shared-ini-file-loader': 4.4.8 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.972.24': + dependencies: + '@aws-sdk/core': 3.973.26 + '@aws-sdk/types': 3.973.6 + '@smithy/property-provider': 4.2.13 + '@smithy/shared-ini-file-loader': 4.4.8 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.972.28': + dependencies: + '@aws-sdk/core': 3.973.26 + '@aws-sdk/nested-clients': 3.996.18 + '@aws-sdk/token-providers': 3.1021.0 + '@aws-sdk/types': 3.973.6 + '@smithy/property-provider': 4.2.13 + '@smithy/shared-ini-file-loader': 4.4.8 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.972.28': + dependencies: + '@aws-sdk/core': 3.973.26 + '@aws-sdk/nested-clients': 3.996.18 + '@aws-sdk/types': 3.973.6 + '@smithy/property-provider': 4.2.13 + '@smithy/shared-ini-file-loader': 4.4.8 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/middleware-bucket-endpoint@3.972.8': + dependencies: + '@aws-sdk/types': 3.973.6 + '@aws-sdk/util-arn-parser': 3.972.3 + '@smithy/node-config-provider': 4.3.13 + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + '@smithy/util-config-provider': 4.2.2 + tslib: 2.8.1 + + '@aws-sdk/middleware-expect-continue@3.972.8': + dependencies: + '@aws-sdk/types': 3.973.6 + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-flexible-checksums@3.974.6': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/core': 3.973.26 + '@aws-sdk/crc64-nvme': 3.972.5 + '@aws-sdk/types': 3.973.6 + '@smithy/is-array-buffer': 4.2.2 + '@smithy/node-config-provider': 4.3.13 + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + '@smithy/util-middleware': 4.2.13 + '@smithy/util-stream': 4.5.22 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@aws-sdk/middleware-host-header@3.972.8': + dependencies: + '@aws-sdk/types': 3.973.6 + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-location-constraint@3.972.8': + dependencies: + '@aws-sdk/types': 3.973.6 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.972.8': + dependencies: + '@aws-sdk/types': 3.973.6 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.972.9': + dependencies: + '@aws-sdk/types': 3.973.6 + '@aws/lambda-invoke-store': 0.2.4 + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.972.27': + dependencies: + '@aws-sdk/core': 3.973.26 + '@aws-sdk/types': 3.973.6 + '@aws-sdk/util-arn-parser': 3.972.3 + '@smithy/core': 3.23.14 + '@smithy/node-config-provider': 4.3.13 + '@smithy/protocol-http': 5.3.13 + '@smithy/signature-v4': 5.3.13 + '@smithy/smithy-client': 4.12.9 + '@smithy/types': 4.14.0 + '@smithy/util-config-provider': 4.2.2 + '@smithy/util-middleware': 4.2.13 + '@smithy/util-stream': 4.5.22 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@aws-sdk/middleware-ssec@3.972.8': + dependencies: + '@aws-sdk/types': 3.973.6 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.972.28': + dependencies: + '@aws-sdk/core': 3.973.26 + '@aws-sdk/types': 3.973.6 + '@aws-sdk/util-endpoints': 3.996.5 + '@smithy/core': 3.23.14 + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + '@smithy/util-retry': 4.3.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.996.18': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.973.26 + '@aws-sdk/middleware-host-header': 3.972.8 + '@aws-sdk/middleware-logger': 3.972.8 + '@aws-sdk/middleware-recursion-detection': 3.972.9 + '@aws-sdk/middleware-user-agent': 3.972.28 + '@aws-sdk/region-config-resolver': 3.972.10 + '@aws-sdk/types': 3.973.6 + '@aws-sdk/util-endpoints': 3.996.5 + '@aws-sdk/util-user-agent-browser': 3.972.8 + '@aws-sdk/util-user-agent-node': 3.973.14 + '@smithy/config-resolver': 4.4.14 + '@smithy/core': 3.23.14 + '@smithy/fetch-http-handler': 5.3.16 + '@smithy/hash-node': 4.2.13 + '@smithy/invalid-dependency': 4.2.13 + '@smithy/middleware-content-length': 4.2.13 + '@smithy/middleware-endpoint': 4.4.29 + '@smithy/middleware-retry': 4.5.0 + '@smithy/middleware-serde': 4.2.17 + '@smithy/middleware-stack': 4.2.13 + '@smithy/node-config-provider': 4.3.13 + '@smithy/node-http-handler': 4.5.2 + '@smithy/protocol-http': 5.3.13 + '@smithy/smithy-client': 4.12.9 + '@smithy/types': 4.14.0 + '@smithy/url-parser': 4.2.13 + '@smithy/util-base64': 4.3.2 + '@smithy/util-body-length-browser': 4.2.2 + '@smithy/util-body-length-node': 4.2.3 + '@smithy/util-defaults-mode-browser': 4.3.45 + '@smithy/util-defaults-mode-node': 4.2.49 + '@smithy/util-endpoints': 3.3.4 + '@smithy/util-middleware': 4.2.13 + '@smithy/util-retry': 4.3.0 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.6 + '@smithy/config-resolver': 4.4.14 + '@smithy/node-config-provider': 4.3.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.996.15': + dependencies: + '@aws-sdk/middleware-sdk-s3': 3.972.27 + '@aws-sdk/types': 3.973.6 + '@smithy/protocol-http': 5.3.13 + '@smithy/signature-v4': 5.3.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1021.0': + dependencies: + '@aws-sdk/core': 3.973.26 + '@aws-sdk/nested-clients': 3.996.18 + '@aws-sdk/types': 3.973.6 + '@smithy/property-provider': 4.2.13 + '@smithy/shared-ini-file-loader': 4.4.8 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.973.6': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@aws-sdk/util-arn-parser@3.972.3': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.996.5': + dependencies: + '@aws-sdk/types': 3.973.6 + '@smithy/types': 4.14.0 + '@smithy/url-parser': 4.2.13 + '@smithy/util-endpoints': 3.3.4 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.965.5': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.972.8': + dependencies: + '@aws-sdk/types': 3.973.6 + '@smithy/types': 4.14.0 + bowser: 2.14.1 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.973.14': + dependencies: + '@aws-sdk/middleware-user-agent': 3.972.28 + '@aws-sdk/types': 3.973.6 + '@smithy/node-config-provider': 4.3.13 + '@smithy/types': 4.14.0 + '@smithy/util-config-provider': 4.2.2 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.972.16': + dependencies: + '@smithy/types': 4.14.0 + fast-xml-parser: 5.5.8 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.2.4': {} + + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/runtime@7.28.6': {} + + '@borewit/text-codec@0.2.2': {} + + '@cfworker/json-schema@4.1.1': {} + + '@configvault.io/interfaces@1.0.17': + dependencies: + '@api.global/typedrequest-interfaces': 3.0.19 + + '@design.estate/dees-comms@1.0.30': + dependencies: + '@api.global/typedrequest': 3.3.0 + '@api.global/typedrequest-interfaces': 3.0.19 + '@push.rocks/smartdelay': 3.0.5 + broadcast-channel: 7.3.0 + + '@design.estate/dees-domtools@2.5.4': + dependencies: + '@api.global/typedrequest': 3.3.0 + '@design.estate/dees-comms': 1.0.30 + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartjson': 6.0.0 + '@push.rocks/smartmarkdown': 3.0.3 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrouter': 1.3.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartstate': 2.3.0 + '@push.rocks/smartstring': 4.1.0 + '@push.rocks/smarturl': 3.1.0 + '@push.rocks/webrequest': 4.0.5 + '@push.rocks/websetup': 3.0.19 + '@push.rocks/webstore': 2.0.21 + '@tempfix/lenis': 1.3.20 + lit: 3.3.2 + sweet-scroll: 4.0.0 + transitivePeerDependencies: + - '@nuxt/kit' + - react + - supports-color + - vue + + '@design.estate/dees-element@2.2.4': + dependencies: + '@design.estate/dees-domtools': 2.5.4 + '@push.rocks/isounique': 1.0.5 + '@push.rocks/smartrx': 3.0.10 + lit: 3.3.2 + transitivePeerDependencies: + - '@nuxt/kit' + - react + - supports-color + - vue + + '@emnapi/core@1.9.2': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.9.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.27.7': + optional: true + + '@esbuild/android-arm64@0.27.7': + optional: true + + '@esbuild/android-arm@0.27.7': + optional: true + + '@esbuild/android-x64@0.27.7': + optional: true + + '@esbuild/darwin-arm64@0.27.7': + optional: true + + '@esbuild/darwin-x64@0.27.7': + optional: true + + '@esbuild/freebsd-arm64@0.27.7': + optional: true + + '@esbuild/freebsd-x64@0.27.7': + optional: true + + '@esbuild/linux-arm64@0.27.7': + optional: true + + '@esbuild/linux-arm@0.27.7': + optional: true + + '@esbuild/linux-ia32@0.27.7': + optional: true + + '@esbuild/linux-loong64@0.27.7': + optional: true + + '@esbuild/linux-mips64el@0.27.7': + optional: true + + '@esbuild/linux-ppc64@0.27.7': + optional: true + + '@esbuild/linux-riscv64@0.27.7': + optional: true + + '@esbuild/linux-s390x@0.27.7': + optional: true + + '@esbuild/linux-x64@0.27.7': + optional: true + + '@esbuild/netbsd-arm64@0.27.7': + optional: true + + '@esbuild/netbsd-x64@0.27.7': + optional: true + + '@esbuild/openbsd-arm64@0.27.7': + optional: true + + '@esbuild/openbsd-x64@0.27.7': + optional: true + + '@esbuild/openharmony-arm64@0.27.7': + optional: true + + '@esbuild/sunos-x64@0.27.7': + optional: true + + '@esbuild/win32-arm64@0.27.7': + optional: true + + '@esbuild/win32-ia32@0.27.7': + optional: true + + '@esbuild/win32-x64@0.27.7': + optional: true + + '@git.zone/tsbuild@4.4.0': + dependencies: + '@git.zone/tspublish': 1.11.5 + '@push.rocks/early': 4.0.4 + '@push.rocks/smartcli': 4.0.20 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartfile': 13.1.2 + '@push.rocks/smartfs': 1.5.0 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + typescript: 6.0.2 + transitivePeerDependencies: + - '@nuxt/kit' + - aws-crt + - bare-abort-controller + - bare-buffer + - react + - react-native-b4a + - supports-color + - vue + + '@git.zone/tsbundle@2.10.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + dependencies: + '@push.rocks/early': 4.0.4 + '@push.rocks/smartcli': 4.0.20 + '@push.rocks/smartconfig': 6.1.0 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartfs': 1.5.0 + '@push.rocks/smartinteract': 2.0.16 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartlog-destination-local': 9.0.2 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartspawn': 3.0.3 + '@rspack/core': 1.7.11 + '@types/html-minifier': 4.0.6 + esbuild: 0.27.7 + html-minifier: 4.0.0 + rolldown: 1.0.0-rc.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + typescript: 6.0.2 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + - '@nuxt/kit' + - '@swc/helpers' + - react + - supports-color + - vue + + '@git.zone/tspublish@1.11.5': + dependencies: + '@push.rocks/consolecolor': 2.0.3 + '@push.rocks/smartcli': 4.0.20 + '@push.rocks/smartconfig': 6.1.0 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartfile': 13.1.2 + '@push.rocks/smartfs': 1.5.0 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartnpm': 2.0.6 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartrequest': 5.0.1 + '@push.rocks/smartshell': 3.3.8 + transitivePeerDependencies: + - '@nuxt/kit' + - aws-crt + - bare-abort-controller + - bare-buffer + - react + - react-native-b4a + - supports-color + - vue + + '@git.zone/tsrun@2.0.2': + dependencies: + '@push.rocks/smartfile': 13.1.2 + '@push.rocks/smartshell': 3.3.8 + tsx: 4.21.0 + + '@git.zone/tstest@3.6.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(socks@2.8.7)(typescript@6.0.2)': + dependencies: + '@git.zone/tsbundle': 2.10.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@git.zone/tsrun': 2.0.2 + '@push.rocks/consolecolor': 2.0.3 + '@push.rocks/qenv': 6.1.3 + '@push.rocks/smartbrowser': 2.0.11(typescript@6.0.2) + '@push.rocks/smartcrypto': 2.0.4 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartexpect': 2.5.0 + '@push.rocks/smartfile': 13.1.2 + '@push.rocks/smartfs': 1.5.0 + '@push.rocks/smartjson': 6.0.0 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartmongo': 5.1.1(socks@2.8.7) + '@push.rocks/smartnetwork': 4.5.2 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrequest': 5.0.1 + '@push.rocks/smartserve': 2.0.3 + '@push.rocks/smartshell': 3.3.8 + '@push.rocks/smartstorage': 6.3.2 + '@push.rocks/smarttime': 4.2.3 + '@push.rocks/smartwatch': 6.4.0 + '@types/ws': 8.18.1 + figures: 6.1.0 + ws: 8.20.0 + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@emnapi/core' + - '@emnapi/runtime' + - '@mongodb-js/zstd' + - '@nuxt/kit' + - '@swc/helpers' + - aws-crt + - bare-abort-controller + - bare-buffer + - bufferutil + - gcp-metadata + - kerberos + - mongodb-client-encryption + - react + - react-native-b4a + - snappy + - socks + - supports-color + - typescript + - utf-8-validate + - vue + + '@img/colour@1.1.0': {} + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.9.2 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + + '@inquirer/checkbox@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 2.0.0 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.3 + + '@inquirer/confirm@4.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + + '@inquirer/core@9.2.1': + dependencies: + '@inquirer/figures': 1.0.15 + '@inquirer/type': 2.0.0 + '@types/mute-stream': 0.0.4 + '@types/node': 22.19.17 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + + '@inquirer/editor@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + external-editor: 3.1.0 + + '@inquirer/expand@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + yoctocolors-cjs: 2.1.3 + + '@inquirer/figures@1.0.15': {} + + '@inquirer/input@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + + '@inquirer/number@2.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + + '@inquirer/password@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + ansi-escapes: 4.3.2 + + '@inquirer/prompts@6.0.1': + dependencies: + '@inquirer/checkbox': 3.0.1 + '@inquirer/confirm': 4.0.1 + '@inquirer/editor': 3.0.1 + '@inquirer/expand': 3.0.1 + '@inquirer/input': 3.0.1 + '@inquirer/number': 2.0.1 + '@inquirer/password': 3.0.1 + '@inquirer/rawlist': 3.0.1 + '@inquirer/search': 2.0.1 + '@inquirer/select': 3.0.1 + + '@inquirer/rawlist@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + yoctocolors-cjs: 2.1.3 + + '@inquirer/search@2.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 2.0.0 + yoctocolors-cjs: 2.1.3 + + '@inquirer/select@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 2.0.0 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.3 + + '@inquirer/type@2.0.0': + dependencies: + mute-stream: 1.0.0 + + '@isaacs/cliui@9.0.0': {} + + '@jimp/core@1.6.0': + dependencies: + '@jimp/file-ops': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + await-to-js: 3.0.0 + exif-parser: 0.1.12 + file-type: 16.5.4 + mime: 3.0.0 + + '@jimp/diff@1.6.0': + dependencies: + '@jimp/plugin-resize': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + pixelmatch: 5.3.0 + + '@jimp/file-ops@1.6.0': {} + + '@jimp/js-bmp@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + bmp-ts: 1.0.9 + + '@jimp/js-gif@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + gifwrap: 0.10.1 + omggif: 1.0.10 + + '@jimp/js-jpeg@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + jpeg-js: 0.4.4 + + '@jimp/js-png@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + pngjs: 7.0.0 + + '@jimp/js-tiff@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + utif2: 4.1.0 + + '@jimp/plugin-blit@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-blur@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/utils': 1.6.0 + + '@jimp/plugin-circle@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-color@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + tinycolor2: 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-contain@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/plugin-blit': 1.6.0 + '@jimp/plugin-resize': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-cover@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/plugin-crop': 1.6.0 + '@jimp/plugin-resize': 1.6.0 + '@jimp/types': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-crop@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-displace@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-dither@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + + '@jimp/plugin-fisheye@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-flip@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-hash@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/js-bmp': 1.6.0 + '@jimp/js-jpeg': 1.6.0 + '@jimp/js-png': 1.6.0 + '@jimp/js-tiff': 1.6.0 + '@jimp/plugin-color': 1.6.0 + '@jimp/plugin-resize': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + any-base: 1.1.0 + + '@jimp/plugin-mask@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-print@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/js-jpeg': 1.6.0 + '@jimp/js-png': 1.6.0 + '@jimp/plugin-blit': 1.6.0 + '@jimp/types': 1.6.0 + parse-bmfont-ascii: 1.0.6 + parse-bmfont-binary: 1.0.6 + parse-bmfont-xml: 1.1.6 + simple-xml-to-json: 1.2.7 + zod: 3.25.76 + + '@jimp/plugin-quantize@1.6.0': + dependencies: + image-q: 4.0.0 + zod: 3.25.76 + + '@jimp/plugin-resize@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-rotate@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/plugin-crop': 1.6.0 + '@jimp/plugin-resize': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-threshold@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/plugin-color': 1.6.0 + '@jimp/plugin-hash': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/types@1.6.0': + dependencies: + zod: 3.25.76 + + '@jimp/utils@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + tinycolor2: 1.6.0 + + '@lit-labs/ssr-dom-shim@1.5.1': {} + + '@lit/reactive-element@2.1.2': + dependencies: + '@lit-labs/ssr-dom-shim': 1.5.1 + + '@mixmark-io/domino@2.2.0': {} + + '@module-federation/error-codes@0.22.0': {} + + '@module-federation/runtime-core@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@module-federation/runtime-tools@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/webpack-bundler-runtime': 0.22.0 + + '@module-federation/runtime@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/runtime-core': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@module-federation/sdk@0.22.0': {} + + '@module-federation/webpack-bundler-runtime@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 + + '@mongodb-js/saslprep@1.4.6': + dependencies: + sparse-bitfield: 3.0.3 + + '@napi-rs/wasm-runtime@1.0.7': + dependencies: + '@emnapi/core': 1.9.2 + '@emnapi/runtime': 1.9.2 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@napi-rs/wasm-runtime@1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + dependencies: + '@emnapi/core': 1.9.2 + '@emnapi/runtime': 1.9.2 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@oxc-project/types@0.122.0': {} + + '@pdf-lib/standard-fonts@1.0.0': + dependencies: + pako: 1.0.11 + + '@pdf-lib/upng@1.0.1': + dependencies: + pako: 1.0.11 + + '@peculiar/asn1-cms@2.6.1': + dependencies: + '@peculiar/asn1-schema': 2.6.0 + '@peculiar/asn1-x509': 2.6.1 + '@peculiar/asn1-x509-attr': 2.6.1 + asn1js: 3.0.7 + tslib: 2.8.1 + + '@peculiar/asn1-csr@2.6.1': + dependencies: + '@peculiar/asn1-schema': 2.6.0 + '@peculiar/asn1-x509': 2.6.1 + asn1js: 3.0.7 + tslib: 2.8.1 + + '@peculiar/asn1-ecc@2.6.1': + dependencies: + '@peculiar/asn1-schema': 2.6.0 + '@peculiar/asn1-x509': 2.6.1 + asn1js: 3.0.7 + tslib: 2.8.1 + + '@peculiar/asn1-pfx@2.6.1': + dependencies: + '@peculiar/asn1-cms': 2.6.1 + '@peculiar/asn1-pkcs8': 2.6.1 + '@peculiar/asn1-rsa': 2.6.1 + '@peculiar/asn1-schema': 2.6.0 + asn1js: 3.0.7 + tslib: 2.8.1 + + '@peculiar/asn1-pkcs8@2.6.1': + dependencies: + '@peculiar/asn1-schema': 2.6.0 + '@peculiar/asn1-x509': 2.6.1 + asn1js: 3.0.7 + tslib: 2.8.1 + + '@peculiar/asn1-pkcs9@2.6.1': + dependencies: + '@peculiar/asn1-cms': 2.6.1 + '@peculiar/asn1-pfx': 2.6.1 + '@peculiar/asn1-pkcs8': 2.6.1 + '@peculiar/asn1-schema': 2.6.0 + '@peculiar/asn1-x509': 2.6.1 + '@peculiar/asn1-x509-attr': 2.6.1 + asn1js: 3.0.7 + tslib: 2.8.1 + + '@peculiar/asn1-rsa@2.6.1': + dependencies: + '@peculiar/asn1-schema': 2.6.0 + '@peculiar/asn1-x509': 2.6.1 + asn1js: 3.0.7 + tslib: 2.8.1 + + '@peculiar/asn1-schema@2.6.0': + dependencies: + asn1js: 3.0.7 + pvtsutils: 1.3.6 + tslib: 2.8.1 + + '@peculiar/asn1-x509-attr@2.6.1': + dependencies: + '@peculiar/asn1-schema': 2.6.0 + '@peculiar/asn1-x509': 2.6.1 + asn1js: 3.0.7 + tslib: 2.8.1 + + '@peculiar/asn1-x509@2.6.1': + dependencies: + '@peculiar/asn1-schema': 2.6.0 + asn1js: 3.0.7 + pvtsutils: 1.3.6 + tslib: 2.8.1 + + '@peculiar/x509@1.14.3': + dependencies: + '@peculiar/asn1-cms': 2.6.1 + '@peculiar/asn1-csr': 2.6.1 + '@peculiar/asn1-ecc': 2.6.1 + '@peculiar/asn1-pkcs9': 2.6.1 + '@peculiar/asn1-rsa': 2.6.1 + '@peculiar/asn1-schema': 2.6.0 + '@peculiar/asn1-x509': 2.6.1 + pvtsutils: 1.3.6 + reflect-metadata: 0.2.2 + tslib: 2.8.1 + tsyringe: 4.10.0 + + '@pnpm/config.env-replace@1.1.0': {} + + '@pnpm/network.ca-file@1.0.2': + dependencies: + graceful-fs: 4.2.10 + + '@pnpm/npm-conf@3.0.2': + dependencies: + '@pnpm/config.env-replace': 1.1.0 + '@pnpm/network.ca-file': 1.0.2 + config-chain: 1.1.13 + + '@puppeteer/browsers@2.13.0': + dependencies: + debug: 4.4.3 + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.5.0 + semver: 7.7.4 + tar-fs: 3.1.2 + yargs: 17.7.2 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + - supports-color + + '@push.rocks/consolecolor@2.0.3': + dependencies: + ansi-256-colors: 1.1.0 + + '@push.rocks/early@4.0.4': + dependencies: + '@push.rocks/consolecolor': 2.0.3 + '@push.rocks/smartpromise': 4.2.3 + + '@push.rocks/isounique@1.0.5': {} + + '@push.rocks/levelcache@3.2.0': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartbucket': 3.3.10 + '@push.rocks/smartcache': 1.0.18 + '@push.rocks/smartenv': 5.0.13 + '@push.rocks/smartexit': 1.1.1 + '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartstring': 4.1.0 + '@push.rocks/smartunique': 3.0.9 + '@push.rocks/taskbuffer': 3.5.0 + '@tsclass/tsclass': 9.5.0 + transitivePeerDependencies: + - '@nuxt/kit' + - aws-crt + - react + - supports-color + - vue + + '@push.rocks/lik@6.4.0': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartmatch': 2.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smarttime': 4.2.3 + symbol-tree: 3.2.4 + + '@push.rocks/mongodump@1.1.0(socks@2.8.7)': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@tsclass/tsclass': 9.5.0 + mongodb: 6.21.0(socks@2.8.7) + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - gcp-metadata + - kerberos + - mongodb-client-encryption + - snappy + - socks + + '@push.rocks/qenv@6.1.3': + dependencies: + '@api.global/typedrequest': 3.3.0 + '@configvault.io/interfaces': 1.0.17 + '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartpath': 6.0.0 + + '@push.rocks/smartarchive@4.2.4': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartfile': 13.1.2 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrequest': 4.4.2 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartstream': 3.4.0 + '@push.rocks/smartunique': 3.0.9 + '@push.rocks/smarturl': 3.1.0 + '@types/tar-stream': 3.1.4 + fflate: 0.8.2 + file-type: 21.3.4 + tar-stream: 3.1.8 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + - supports-color + + '@push.rocks/smartbrowser@2.0.11(typescript@6.0.2)': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartpdf': 4.2.0(typescript@6.0.2) + '@push.rocks/smartpuppeteer': 2.0.5(typescript@6.0.2) + '@push.rocks/smartunique': 3.0.9 + transitivePeerDependencies: + - '@nuxt/kit' + - aws-crt + - bare-abort-controller + - bare-buffer + - bufferutil + - react + - react-native-b4a + - supports-color + - typescript + - utf-8-validate + - vue + + '@push.rocks/smartbucket@3.3.10': + dependencies: + '@aws-sdk/client-s3': 3.1025.0 + '@push.rocks/smartmime': 2.0.4 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartstream': 3.4.0 + '@push.rocks/smartstring': 4.1.0 + '@push.rocks/smartunique': 3.0.9 + '@tsclass/tsclass': 9.5.0 + transitivePeerDependencies: + - aws-crt + + '@push.rocks/smartbucket@4.6.0': + dependencies: + '@aws-sdk/client-s3': 3.1025.0 + '@push.rocks/smartmime': 2.0.4 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartstream': 3.4.0 + '@push.rocks/smartstring': 4.1.0 + '@push.rocks/smartunique': 3.0.9 + '@tsclass/tsclass': 9.5.0 + minimatch: 10.2.5 + transitivePeerDependencies: + - aws-crt + + '@push.rocks/smartbuffer@3.0.5': + dependencies: + uint8array-extras: 1.5.0 + + '@push.rocks/smartcache@1.0.18': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smarterror': 2.0.1 + '@push.rocks/smarthash': 3.2.6 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smarttime': 4.2.3 + + '@push.rocks/smartcli@4.0.20': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartobject': 1.0.12 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + yargs-parser: 22.0.0 + + '@push.rocks/smartclickhouse@2.2.0': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartobject': 1.0.12 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smarturl': 3.1.0 + '@push.rocks/webrequest': 4.0.5 + + '@push.rocks/smartconfig@6.1.0': + dependencies: + '@push.rocks/qenv': 6.1.3 + '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/taskbuffer': 3.5.0 + '@tsclass/tsclass': 9.5.0 + transitivePeerDependencies: + - '@nuxt/kit' + - react + - supports-color + - vue + + '@push.rocks/smartcrypto@2.0.4': + dependencies: + '@push.rocks/smartpromise': 4.2.3 + '@types/node-forge': 1.3.14 + node-forge: 1.4.0 + + '@push.rocks/smartdata@7.1.7(socks@2.8.7)': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartmongo': 5.1.1(socks@2.8.7) + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smartstring': 4.1.0 + '@push.rocks/smarttime': 4.2.3 + '@push.rocks/smartunique': 3.0.9 + '@push.rocks/taskbuffer': 8.0.2 + '@tsclass/tsclass': 9.5.0 + mongodb: 7.1.1(socks@2.8.7) + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - '@nuxt/kit' + - bare-abort-controller + - bare-buffer + - gcp-metadata + - kerberos + - mongodb-client-encryption + - react + - react-native-b4a + - snappy + - socks + - supports-color + - vue + + '@push.rocks/smartdelay@3.0.5': + dependencies: + '@push.rocks/smartpromise': 4.2.3 + + '@push.rocks/smartdns@7.9.0': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrust': 1.3.2 + '@tsclass/tsclass': 9.5.0 + acme-client: 5.4.0 + minimatch: 10.2.5 + transitivePeerDependencies: + - supports-color + + '@push.rocks/smartenv@5.0.13': + dependencies: + '@push.rocks/smartpromise': 4.2.3 + + '@push.rocks/smartenv@6.0.0': + dependencies: + '@push.rocks/smartpromise': 4.2.3 + + '@push.rocks/smarterror@2.0.1': + dependencies: + clean-stack: 1.3.0 + make-error-cause: 2.3.0 + + '@push.rocks/smartexit@1.1.1': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartpromise': 4.2.3 + tree-kill: 1.2.2 + + '@push.rocks/smartexit@2.0.3': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartpromise': 4.2.3 + + '@push.rocks/smartexpect@2.5.0': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartpromise': 4.2.3 + fast-deep-equal: 3.1.3 + + '@push.rocks/smartfile-interfaces@1.0.7': {} + + '@push.rocks/smartfile@11.2.7': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartfile-interfaces': 1.0.7 + '@push.rocks/smarthash': 3.2.6 + '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartmime': 2.0.4 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrequest': 4.4.2 + '@push.rocks/smartstream': 3.4.0 + '@types/fs-extra': 11.0.4 + '@types/js-yaml': 4.0.9 + fs-extra: 11.3.4 + glob: 11.1.0 + js-yaml: 4.1.1 + + '@push.rocks/smartfile@13.1.2': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartfile-interfaces': 1.0.7 + '@push.rocks/smartfs': 1.5.0 + '@push.rocks/smarthash': 3.2.6 + '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartmime': 2.0.4 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrequest': 4.4.2 + '@push.rocks/smartstream': 3.4.0 + '@types/js-yaml': 4.0.9 + glob: 11.1.0 + js-yaml: 4.1.1 + + '@push.rocks/smartfs@1.5.0': + dependencies: + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartrust': 1.3.2 + + '@push.rocks/smartguard@3.1.0': + dependencies: + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrequest': 2.1.0 + + '@push.rocks/smarthash@3.2.6': + dependencies: + '@push.rocks/smartenv': 5.0.13 + '@push.rocks/smartjson': 5.2.0 + '@push.rocks/smartpromise': 4.2.3 + '@types/through2': 2.0.41 + through2: 4.0.2 + + '@push.rocks/smartinteract@2.0.16': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartobject': 1.0.12 + '@push.rocks/smartpromise': 4.2.3 + inquirer: 11.1.0 + + '@push.rocks/smartjimp@1.2.0': + dependencies: + '@push.rocks/levelcache': 3.2.0 + '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smarthash': 3.2.6 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartrequest': 4.4.2 + jimp: 1.6.0 + sharp: 0.34.5 + transitivePeerDependencies: + - '@nuxt/kit' + - aws-crt + - react + - supports-color + - vue + + '@push.rocks/smartjson@5.2.0': + dependencies: + '@push.rocks/smartenv': 5.0.13 + '@push.rocks/smartstring': 4.1.0 + fast-json-stable-stringify: 2.1.0 + lodash.clonedeep: 4.5.0 + + '@push.rocks/smartjson@6.0.0': + dependencies: + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartstring': 4.1.0 + fast-json-stable-stringify: 2.1.0 + lodash.clonedeep: 4.5.0 + + '@push.rocks/smartlog-destination-local@9.0.2': + dependencies: + '@push.rocks/consolecolor': 2.0.3 + '@push.rocks/smartlog-interfaces': 3.0.2 + '@push.rocks/smartpromise': 4.2.3 + + '@push.rocks/smartlog-interfaces@3.0.2': + dependencies: + '@api.global/typedrequest-interfaces': 2.0.2 + '@tsclass/tsclass': 4.4.4 + + '@push.rocks/smartlog@3.2.1': + dependencies: + '@api.global/typedrequest-interfaces': 3.0.19 + '@push.rocks/consolecolor': 2.0.3 + '@push.rocks/isounique': 1.0.5 + '@push.rocks/smartclickhouse': 2.2.0 + '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smarthash': 3.2.6 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smarttime': 4.2.3 + '@push.rocks/webrequest': 4.0.5 + '@tsclass/tsclass': 9.5.0 + + '@push.rocks/smartmarkdown@3.0.3': + dependencies: + '@push.rocks/smartyaml': 2.0.5 + '@types/turndown': 5.0.6 + remark-frontmatter: 5.0.0 + remark-gfm: 4.0.1 + remark-html: 16.0.1 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + turndown: 7.2.4 + turndown-plugin-gfm: 1.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + '@push.rocks/smartmatch@2.0.0': + dependencies: + matcher: 5.0.0 + + '@push.rocks/smartmime@2.0.4': + dependencies: + '@types/mime-types': 2.1.4 + file-type: 19.6.0 + mime: 4.1.0 + + '@push.rocks/smartmongo@5.1.1(socks@2.8.7)': + dependencies: + '@push.rocks/mongodump': 1.1.0(socks@2.8.7) + '@push.rocks/smartdata': 7.1.7(socks@2.8.7) + '@push.rocks/smartfs': 1.5.0 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + bson: 7.2.0 + mingo: 7.2.1 + mongodb-memory-server: 11.0.1(socks@2.8.7) + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - '@nuxt/kit' + - bare-abort-controller + - bare-buffer + - gcp-metadata + - kerberos + - mongodb-client-encryption + - react + - react-native-b4a + - snappy + - socks + - supports-color + - vue + + '@push.rocks/smartnetwork@4.5.2': + dependencies: + '@push.rocks/smartdns': 7.9.0 + '@push.rocks/smartrust': 1.3.2 + maxmind: 5.0.6 + transitivePeerDependencies: + - supports-color + + '@push.rocks/smartnpm@2.0.6': + dependencies: + '@push.rocks/consolecolor': 2.0.3 + '@push.rocks/levelcache': 3.2.0 + '@push.rocks/smartarchive': 4.2.4 + '@push.rocks/smartfile': 11.2.7 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrequest': 4.4.2 + '@push.rocks/smarttime': 4.2.3 + '@push.rocks/smartversion': 3.1.0 + package-json: 8.1.1 + transitivePeerDependencies: + - '@nuxt/kit' + - aws-crt + - bare-abort-controller + - bare-buffer + - react + - react-native-b4a + - supports-color + - vue + + '@push.rocks/smartobject@1.0.12': + dependencies: + fast-deep-equal: 3.1.3 + minimatch: 9.0.9 + + '@push.rocks/smartpath@6.0.0': {} + + '@push.rocks/smartpdf@4.2.0(typescript@6.0.2)': + dependencies: + '@push.rocks/smartbuffer': 3.0.5 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartfs': 1.5.0 + '@push.rocks/smartjimp': 1.2.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) + '@push.rocks/smartserve': 2.0.3 + '@push.rocks/smartunique': 3.0.9 + '@tsclass/tsclass': 9.5.0 + pdf-lib: 1.17.1 + pdf2json: 4.0.2 + transitivePeerDependencies: + - '@nuxt/kit' + - aws-crt + - bare-abort-controller + - bare-buffer + - bufferutil + - react + - react-native-b4a + - supports-color + - typescript + - utf-8-validate + - vue + + '@push.rocks/smartpromise@4.2.3': {} + + '@push.rocks/smartpuppeteer@2.0.5(typescript@6.0.2)': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartshell': 3.3.8 + puppeteer: 24.40.0(typescript@6.0.2) + tree-kill: 1.2.2 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - bufferutil + - react-native-b4a + - supports-color + - typescript + - utf-8-validate + + '@push.rocks/smartrequest@2.1.0': + dependencies: + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smarturl': 3.1.0 + agentkeepalive: 4.6.0 + form-data: 4.0.5 + + '@push.rocks/smartrequest@4.4.2': + dependencies: + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smarturl': 3.1.0 + agentkeepalive: 4.6.0 + form-data: 4.0.5 + + '@push.rocks/smartrequest@5.0.1': + dependencies: + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smarturl': 3.1.0 + agentkeepalive: 4.6.0 + form-data: 4.0.5 + + '@push.rocks/smartrouter@1.3.3': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartrx': 3.0.10 + path-to-regexp: 8.4.2 + + '@push.rocks/smartrust@1.3.2': + dependencies: + '@push.rocks/smartpath': 6.0.0 + + '@push.rocks/smartrx@3.0.10': + dependencies: + '@push.rocks/smartpromise': 4.2.3 + rxjs: 7.8.2 + + '@push.rocks/smartserve@2.0.3': + dependencies: + '@api.global/typedrequest': 3.3.0 + '@cfworker/json-schema': 4.1.1 + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartpath': 6.0.0 + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@push.rocks/smartshell@3.3.8': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartexit': 2.0.3 + '@push.rocks/smartpromise': 4.2.3 + '@types/which': 3.0.4 + which: 6.0.1 + + '@push.rocks/smartspawn@3.0.3': + dependencies: + '@push.rocks/smartpromise': 4.2.3 + spawn-wrap: 2.0.0 + threads: 1.7.0 + tiny-worker: 2.3.0 + transitivePeerDependencies: + - supports-color + + '@push.rocks/smartstate@2.3.0': + dependencies: + '@push.rocks/smarthash': 3.2.6 + '@push.rocks/smartjson': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/webstore': 2.0.21 + + '@push.rocks/smartstorage@6.3.2': + dependencies: + '@push.rocks/smartpath': 6.0.0 + '@push.rocks/smartrust': 1.3.2 + '@tsclass/tsclass': 9.5.0 + + '@push.rocks/smartstream@3.4.0': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + + '@push.rocks/smartstring@4.1.0': + dependencies: + '@push.rocks/isounique': 1.0.5 + + '@push.rocks/smarttime@4.2.3': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartpromise': 4.2.3 + croner: 10.0.1 + date-fns: 4.1.0 + dayjs: 1.11.20 + is-nan: 1.3.2 + pretty-ms: 9.3.0 + + '@push.rocks/smartunique@3.0.9': + dependencies: + '@types/uuid': 9.0.8 + nanoid: 4.0.2 + uuid: 9.0.1 + + '@push.rocks/smarturl@3.1.0': {} + + '@push.rocks/smartversion@3.1.0': + dependencies: + '@types/semver': 7.7.1 + semver: 7.7.4 + + '@push.rocks/smartwatch@6.4.0': + dependencies: + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrust': 1.3.2 + '@push.rocks/smartrx': 3.0.10 + chokidar: 5.0.0 + picomatch: 4.0.4 + + '@push.rocks/smartyaml@2.0.5': + dependencies: + '@types/js-yaml': 3.12.10 + js-yaml: 3.14.2 + + '@push.rocks/taskbuffer@3.5.0': + dependencies: + '@design.estate/dees-element': 2.2.4 + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smarttime': 4.2.3 + '@push.rocks/smartunique': 3.0.9 + transitivePeerDependencies: + - '@nuxt/kit' + - react + - supports-color + - vue + + '@push.rocks/taskbuffer@8.0.2': + dependencies: + '@design.estate/dees-element': 2.2.4 + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartlog': 3.2.1 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + '@push.rocks/smarttime': 4.2.3 + '@push.rocks/smartunique': 3.0.9 + transitivePeerDependencies: + - '@nuxt/kit' + - react + - supports-color + - vue + + '@push.rocks/webrequest@4.0.5': + dependencies: + '@push.rocks/smartdelay': 3.0.5 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartjson': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/webstore': 2.0.21 + + '@push.rocks/websetup@3.0.19': + dependencies: + '@pushrocks/smartdelay': 3.0.1 + '@pushrocks/smartpromise': 4.0.2 + '@tsclass/tsclass': 4.4.4 + + '@push.rocks/webstore@2.0.21': + dependencies: + '@api.global/typedrequest-interfaces': 3.0.19 + '@push.rocks/lik': 6.4.0 + '@push.rocks/smartenv': 6.0.0 + '@push.rocks/smartjson': 6.0.0 + '@push.rocks/smartpromise': 4.2.3 + '@push.rocks/smartrx': 3.0.10 + fake-indexeddb: 6.2.5 + idb: 8.0.3 + + '@push.rocks/webstream@1.0.10': + dependencies: + '@push.rocks/smartenv': 5.0.13 + + '@pushrocks/smartdelay@3.0.1': + dependencies: + '@pushrocks/smartpromise': 4.0.2 + + '@pushrocks/smartpromise@4.0.2': {} + + '@rolldown/binding-android-arm64@1.0.0-rc.11': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-rc.11': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-rc.11': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.11': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.11': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + dependencies: + '@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.11': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.11': + optional: true + + '@rolldown/pluginutils@1.0.0-rc.11': {} + + '@rspack/binding-darwin-arm64@1.7.11': + optional: true + + '@rspack/binding-darwin-x64@1.7.11': + optional: true + + '@rspack/binding-linux-arm64-gnu@1.7.11': + optional: true + + '@rspack/binding-linux-arm64-musl@1.7.11': + optional: true + + '@rspack/binding-linux-x64-gnu@1.7.11': + optional: true + + '@rspack/binding-linux-x64-musl@1.7.11': + optional: true + + '@rspack/binding-wasm32-wasi@1.7.11': + dependencies: + '@napi-rs/wasm-runtime': 1.0.7 + optional: true + + '@rspack/binding-win32-arm64-msvc@1.7.11': + optional: true + + '@rspack/binding-win32-ia32-msvc@1.7.11': + optional: true + + '@rspack/binding-win32-x64-msvc@1.7.11': + optional: true + + '@rspack/binding@1.7.11': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.7.11 + '@rspack/binding-darwin-x64': 1.7.11 + '@rspack/binding-linux-arm64-gnu': 1.7.11 + '@rspack/binding-linux-arm64-musl': 1.7.11 + '@rspack/binding-linux-x64-gnu': 1.7.11 + '@rspack/binding-linux-x64-musl': 1.7.11 + '@rspack/binding-wasm32-wasi': 1.7.11 + '@rspack/binding-win32-arm64-msvc': 1.7.11 + '@rspack/binding-win32-ia32-msvc': 1.7.11 + '@rspack/binding-win32-x64-msvc': 1.7.11 + + '@rspack/core@1.7.11': + dependencies: + '@module-federation/runtime-tools': 0.22.0 + '@rspack/binding': 1.7.11 + '@rspack/lite-tapable': 1.1.0 + + '@rspack/lite-tapable@1.1.0': {} + + '@sec-ant/readable-stream@0.4.1': {} + + '@sindresorhus/is@5.6.0': {} + + '@smithy/chunked-blob-reader-native@4.2.3': + dependencies: + '@smithy/util-base64': 4.3.2 + tslib: 2.8.1 + + '@smithy/chunked-blob-reader@5.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/config-resolver@4.4.14': + dependencies: + '@smithy/node-config-provider': 4.3.13 + '@smithy/types': 4.14.0 + '@smithy/util-config-provider': 4.2.2 + '@smithy/util-endpoints': 3.3.4 + '@smithy/util-middleware': 4.2.13 + tslib: 2.8.1 + + '@smithy/core@3.23.14': + dependencies: + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + '@smithy/url-parser': 4.2.13 + '@smithy/util-base64': 4.3.2 + '@smithy/util-body-length-browser': 4.2.2 + '@smithy/util-middleware': 4.2.13 + '@smithy/util-stream': 4.5.22 + '@smithy/util-utf8': 4.2.2 + '@smithy/uuid': 1.1.2 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.2.13': + dependencies: + '@smithy/node-config-provider': 4.3.13 + '@smithy/property-provider': 4.2.13 + '@smithy/types': 4.14.0 + '@smithy/url-parser': 4.2.13 + tslib: 2.8.1 + + '@smithy/eventstream-codec@4.2.13': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.14.0 + '@smithy/util-hex-encoding': 4.2.2 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.2.13': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.3.13': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.2.13': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-universal@4.2.13': + dependencies: + '@smithy/eventstream-codec': 4.2.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.3.16': + dependencies: + '@smithy/protocol-http': 5.3.13 + '@smithy/querystring-builder': 4.2.13 + '@smithy/types': 4.14.0 + '@smithy/util-base64': 4.3.2 + tslib: 2.8.1 + + '@smithy/hash-blob-browser@4.2.14': + dependencies: + '@smithy/chunked-blob-reader': 5.2.2 + '@smithy/chunked-blob-reader-native': 4.2.3 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/hash-node@4.2.13': + dependencies: + '@smithy/types': 4.14.0 + '@smithy/util-buffer-from': 4.2.2 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@smithy/hash-stream-node@4.2.13': + dependencies: + '@smithy/types': 4.14.0 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.2.13': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/is-array-buffer@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/md5-js@4.2.13': + dependencies: + '@smithy/types': 4.14.0 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.2.13': + dependencies: + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.4.29': + dependencies: + '@smithy/core': 3.23.14 + '@smithy/middleware-serde': 4.2.17 + '@smithy/node-config-provider': 4.3.13 + '@smithy/shared-ini-file-loader': 4.4.8 + '@smithy/types': 4.14.0 + '@smithy/url-parser': 4.2.13 + '@smithy/util-middleware': 4.2.13 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.5.0': + dependencies: + '@smithy/core': 3.23.14 + '@smithy/node-config-provider': 4.3.13 + '@smithy/protocol-http': 5.3.13 + '@smithy/service-error-classification': 4.2.13 + '@smithy/smithy-client': 4.12.9 + '@smithy/types': 4.14.0 + '@smithy/util-middleware': 4.2.13 + '@smithy/util-retry': 4.3.0 + '@smithy/uuid': 1.1.2 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.2.17': + dependencies: + '@smithy/core': 3.23.14 + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.2.13': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.3.13': + dependencies: + '@smithy/property-provider': 4.2.13 + '@smithy/shared-ini-file-loader': 4.4.8 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.5.2': + dependencies: + '@smithy/protocol-http': 5.3.13 + '@smithy/querystring-builder': 4.2.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/property-provider@4.2.13': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/protocol-http@5.3.13': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.2.13': + dependencies: + '@smithy/types': 4.14.0 + '@smithy/util-uri-escape': 4.2.2 + tslib: 2.8.1 + + '@smithy/querystring-parser@4.2.13': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/service-error-classification@4.2.13': + dependencies: + '@smithy/types': 4.14.0 + + '@smithy/shared-ini-file-loader@4.4.8': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.3.13': + dependencies: + '@smithy/is-array-buffer': 4.2.2 + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + '@smithy/util-hex-encoding': 4.2.2 + '@smithy/util-middleware': 4.2.13 + '@smithy/util-uri-escape': 4.2.2 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@smithy/smithy-client@4.12.9': + dependencies: + '@smithy/core': 3.23.14 + '@smithy/middleware-endpoint': 4.4.29 + '@smithy/middleware-stack': 4.2.13 + '@smithy/protocol-http': 5.3.13 + '@smithy/types': 4.14.0 + '@smithy/util-stream': 4.5.22 + tslib: 2.8.1 + + '@smithy/types@4.14.0': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.2.13': + dependencies: + '@smithy/querystring-parser': 4.2.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/util-base64@4.3.2': + dependencies: + '@smithy/util-buffer-from': 4.2.2 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@smithy/util-body-length-browser@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/util-body-length-node@4.2.3': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-buffer-from@4.2.2': + dependencies: + '@smithy/is-array-buffer': 4.2.2 + tslib: 2.8.1 + + '@smithy/util-config-provider@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/util-defaults-mode-browser@4.3.45': + dependencies: + '@smithy/property-provider': 4.2.13 + '@smithy/smithy-client': 4.12.9 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/util-defaults-mode-node@4.2.49': + dependencies: + '@smithy/config-resolver': 4.4.14 + '@smithy/credential-provider-imds': 4.2.13 + '@smithy/node-config-provider': 4.3.13 + '@smithy/property-provider': 4.2.13 + '@smithy/smithy-client': 4.12.9 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/util-endpoints@3.3.4': + dependencies: + '@smithy/node-config-provider': 4.3.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/util-middleware@4.2.13': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/util-retry@4.3.0': + dependencies: + '@smithy/service-error-classification': 4.2.13 + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/util-stream@4.5.22': + dependencies: + '@smithy/fetch-http-handler': 5.3.16 + '@smithy/node-http-handler': 4.5.2 + '@smithy/types': 4.14.0 + '@smithy/util-base64': 4.3.2 + '@smithy/util-buffer-from': 4.2.2 + '@smithy/util-hex-encoding': 4.2.2 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@smithy/util-uri-escape@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.2.2': + dependencies: + '@smithy/util-buffer-from': 4.2.2 + tslib: 2.8.1 + + '@smithy/util-waiter@4.2.15': + dependencies: + '@smithy/types': 4.14.0 + tslib: 2.8.1 + + '@smithy/uuid@1.1.2': + dependencies: + tslib: 2.8.1 + + '@szmarczak/http-timer@5.0.1': + dependencies: + defer-to-connect: 2.0.1 + + '@tempfix/lenis@1.3.20': {} + + '@tokenizer/inflate@0.4.1': + dependencies: + debug: 4.4.3 + token-types: 6.1.2 + transitivePeerDependencies: + - supports-color + + '@tokenizer/token@0.3.0': {} + + '@tootallnate/quickjs-emscripten@0.23.0': {} + + '@tsclass/tsclass@4.4.4': + dependencies: + type-fest: 4.41.0 + + '@tsclass/tsclass@9.5.0': + dependencies: + type-fest: 5.5.0 + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/clean-css@4.2.11': + dependencies: + '@types/node': 25.5.2 + source-map: 0.6.1 + + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 25.5.2 + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/html-minifier@4.0.6': + dependencies: + '@types/clean-css': 4.2.11 + '@types/relateurl': 0.2.33 + '@types/uglify-js': 3.17.5 + + '@types/http-cache-semantics@4.2.0': {} + + '@types/js-yaml@3.12.10': {} + + '@types/js-yaml@4.0.9': {} + + '@types/jsonfile@6.1.4': + dependencies: + '@types/node': 25.5.2 + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mime-types@2.1.4': {} + + '@types/ms@2.1.0': {} + + '@types/mute-stream@0.0.4': + dependencies: + '@types/node': 25.5.2 + + '@types/node-forge@1.3.14': + dependencies: + '@types/node': 25.5.2 + + '@types/node@16.9.1': {} + + '@types/node@22.19.17': + dependencies: + undici-types: 6.21.0 + + '@types/node@25.5.2': + dependencies: + undici-types: 7.18.2 + + '@types/relateurl@0.2.33': {} + + '@types/semver@7.7.1': {} + + '@types/tar-stream@3.1.4': + dependencies: + '@types/node': 25.5.2 + + '@types/through2@2.0.41': + dependencies: + '@types/node': 25.5.2 + + '@types/trusted-types@2.0.7': {} + + '@types/turndown@5.0.6': {} + + '@types/uglify-js@3.17.5': + dependencies: + source-map: 0.6.1 + + '@types/unist@3.0.3': {} + + '@types/uuid@9.0.8': {} + + '@types/webidl-conversions@7.0.3': {} + + '@types/whatwg-url@11.0.5': + dependencies: + '@types/webidl-conversions': 7.0.3 + + '@types/whatwg-url@13.0.0': + dependencies: + '@types/webidl-conversions': 7.0.3 + + '@types/which@3.0.4': {} + + '@types/wrap-ansi@3.0.0': {} + + '@types/ws@8.18.1': + dependencies: + '@types/node': 25.5.2 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 25.5.2 + optional: true + + '@ungap/structured-clone@1.3.0': {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + acme-client@5.4.0: + dependencies: + '@peculiar/x509': 1.14.3 + asn1js: 3.0.7 + axios: 1.14.0(debug@4.4.3) + debug: 4.4.3 + node-forge: 1.4.0 + transitivePeerDependencies: + - supports-color + + agent-base@7.1.4: {} + + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + ansi-256-colors@1.1.0: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + any-base@1.1.0: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + asn1js@3.0.7: + dependencies: + pvtsutils: 1.3.6 + pvutils: 1.1.5 + tslib: 2.8.1 + + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + + async-mutex@0.5.0: + dependencies: + tslib: 2.8.1 + + asynckit@0.4.0: {} + + await-to-js@3.0.0: {} + + axios@1.14.0(debug@4.4.3): + dependencies: + follow-redirects: 1.15.11(debug@4.4.3) + form-data: 4.0.5 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + + b4a@1.8.0: {} + + bail@2.0.2: {} + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + bare-events@2.8.2: {} + + bare-fs@4.6.0: + dependencies: + bare-events: 2.8.2 + bare-path: 3.0.0 + bare-stream: 2.12.0(bare-events@2.8.2) + bare-url: 2.4.0 + fast-fifo: 1.3.2 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + bare-os@3.8.7: {} + + bare-path@3.0.0: + dependencies: + bare-os: 3.8.7 + + bare-stream@2.12.0(bare-events@2.8.2): + dependencies: + streamx: 2.25.0 + teex: 1.0.1 + optionalDependencies: + bare-events: 2.8.2 + transitivePeerDependencies: + - react-native-b4a + + bare-url@2.4.0: + dependencies: + bare-path: 3.0.0 + + base64-js@1.5.1: {} + + basic-ftp@5.2.0: {} + + bmp-ts@1.0.9: {} + + bowser@2.14.1: {} + + brace-expansion@1.1.13: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.3: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.5: + dependencies: + balanced-match: 4.0.4 + + broadcast-channel@7.3.0: + dependencies: + '@babel/runtime': 7.28.6 + oblivious-set: 2.0.0 + p-queue: 6.6.2 + unload: 2.4.1 + + bson@6.10.4: {} + + bson@7.2.0: {} + + buffer-crc32@0.2.13: {} + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + cacheable-lookup@7.0.0: {} + + cacheable-request@10.2.14: + dependencies: + '@types/http-cache-semantics': 4.2.0 + get-stream: 6.0.1 + http-cache-semantics: 4.2.0 + keyv: 4.5.4 + mimic-response: 4.0.0 + normalize-url: 8.1.1 + responselike: 3.0.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + callsites@3.1.0: {} + + camel-case@3.0.0: + dependencies: + no-case: 2.3.2 + upper-case: 1.1.3 + + camelcase@6.3.0: {} + + ccount@2.0.1: {} + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + character-entities@2.0.2: {} + + chardet@0.7.0: {} + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + chromium-bidi@14.0.0(devtools-protocol@0.0.1581282): + dependencies: + devtools-protocol: 0.0.1581282 + mitt: 3.0.1 + zod: 3.25.76 + + clean-css@4.2.4: + dependencies: + source-map: 0.6.1 + + clean-stack@1.3.0: {} + + cli-width@4.1.0: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + comma-separated-tokens@2.0.3: {} + + commander@2.20.3: {} + + commondir@1.0.1: {} + + concat-map@0.0.1: {} + + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + + cosmiconfig@9.0.1(typescript@6.0.2): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + optionalDependencies: + typescript: 6.0.2 + + croner@10.0.1: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + data-uri-to-buffer@6.0.2: {} + + date-fns@4.1.0: {} + + dayjs@1.11.20: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decode-named-character-reference@1.3.0: + dependencies: + character-entities: 2.0.2 + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + deep-extend@0.6.0: {} + + defer-to-connect@2.0.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + + delayed-stream@1.0.0: {} + + dequal@2.0.3: {} + + detect-libc@2.1.2: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + devtools-protocol@0.0.1581282: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + emoji-regex@8.0.0: {} + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + env-paths@2.2.1: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + esbuild@0.27.7: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 + + escalade@3.2.0: {} + + escape-string-regexp@5.0.0: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + esm@3.2.25: {} + + esprima@4.0.1: {} + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + event-target-shim@5.0.1: {} + + eventemitter3@4.0.7: {} + + events-universal@1.0.1: + dependencies: + bare-events: 2.8.2 + transitivePeerDependencies: + - bare-abort-controller + + events@3.3.0: {} + + exif-parser@0.1.12: {} + + extend@3.0.2: {} + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + + extract-zip@2.0.1: + dependencies: + debug: 4.4.3 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + + fake-indexeddb@6.2.5: {} + + fast-deep-equal@3.1.3: {} + + fast-fifo@1.3.2: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-xml-builder@1.1.4: + dependencies: + path-expression-matcher: 1.4.0 + + fast-xml-parser@5.5.8: + dependencies: + fast-xml-builder: 1.1.4 + path-expression-matcher: 1.4.0 + strnum: 2.2.3 + + fault@2.0.1: + dependencies: + format: 0.2.2 + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fflate@0.8.2: {} + + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + + file-type@16.5.4: + dependencies: + readable-web-to-node-stream: 3.0.4 + strtok3: 6.3.0 + token-types: 4.2.1 + + file-type@19.6.0: + dependencies: + get-stream: 9.0.1 + strtok3: 9.1.1 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + + file-type@21.3.4: + dependencies: + '@tokenizer/inflate': 0.4.1 + strtok3: 10.3.5 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + + find-cache-dir@3.3.2: + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + follow-redirects@1.15.11(debug@4.4.3): + optionalDependencies: + debug: 4.4.3 + + foreground-child@2.0.0: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 3.0.7 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data-encoder@2.1.4: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + format@0.2.2: {} + + fs-extra@11.3.4: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@5.2.0: + dependencies: + pump: 3.0.4 + + get-stream@6.0.1: {} + + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + + get-tsconfig@4.13.7: + dependencies: + resolve-pkg-maps: 1.0.0 + + get-uri@6.0.5: + dependencies: + basic-ftp: 5.2.0 + data-uri-to-buffer: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + gifwrap@0.10.1: + dependencies: + image-q: 4.0.0 + omggif: 1.0.10 + + glob@11.1.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.2.3 + minimatch: 10.2.5 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.2 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + + gopd@1.2.0: {} + + got@12.6.1: + dependencies: + '@sindresorhus/is': 5.6.0 + '@szmarczak/http-timer': 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 10.2.14 + decompress-response: 6.0.0 + form-data-encoder: 2.1.4 + get-stream: 6.0.1 + http2-wrapper: 2.2.1 + lowercase-keys: 3.0.0 + p-cancelable: 3.0.0 + responselike: 3.0.0 + + graceful-fs@4.2.10: {} + + graceful-fs@4.2.11: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hast-util-sanitize@5.0.2: + dependencies: + '@types/hast': 3.0.4 + '@ungap/structured-clone': 1.3.0 + unist-util-position: 5.0.0 + + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + he@1.2.0: {} + + html-minifier@4.0.0: + dependencies: + camel-case: 3.0.0 + clean-css: 4.2.4 + commander: 2.20.3 + he: 1.2.0 + param-case: 2.1.1 + relateurl: 0.2.7 + uglify-js: 3.19.3 + + html-void-elements@3.0.0: {} + + http-cache-semantics@4.2.0: {} + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + http2-wrapper@2.2.1: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + idb@8.0.3: {} + + ieee754@1.2.1: {} + + image-q@4.0.0: + dependencies: + '@types/node': 16.9.1 + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@1.3.8: {} + + inquirer@11.1.0: + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/prompts': 6.0.1 + '@inquirer/type': 2.0.0 + '@types/mute-stream': 0.0.4 + ansi-escapes: 4.3.2 + mute-stream: 1.0.0 + run-async: 3.0.0 + rxjs: 7.8.2 + + ip-address@10.1.0: {} + + is-arrayish@0.2.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-nan@1.3.2: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + + is-observable@2.1.0: {} + + is-plain-obj@4.1.0: {} + + is-stream@4.0.1: {} + + is-unicode-supported@2.1.0: {} + + is-windows@1.0.2: {} + + isexe@2.0.0: {} + + isexe@4.0.0: {} + + jackspeak@4.2.3: + dependencies: + '@isaacs/cliui': 9.0.0 + + jimp@1.6.0: + dependencies: + '@jimp/core': 1.6.0 + '@jimp/diff': 1.6.0 + '@jimp/js-bmp': 1.6.0 + '@jimp/js-gif': 1.6.0 + '@jimp/js-jpeg': 1.6.0 + '@jimp/js-png': 1.6.0 + '@jimp/js-tiff': 1.6.0 + '@jimp/plugin-blit': 1.6.0 + '@jimp/plugin-blur': 1.6.0 + '@jimp/plugin-circle': 1.6.0 + '@jimp/plugin-color': 1.6.0 + '@jimp/plugin-contain': 1.6.0 + '@jimp/plugin-cover': 1.6.0 + '@jimp/plugin-crop': 1.6.0 + '@jimp/plugin-displace': 1.6.0 + '@jimp/plugin-dither': 1.6.0 + '@jimp/plugin-fisheye': 1.6.0 + '@jimp/plugin-flip': 1.6.0 + '@jimp/plugin-hash': 1.6.0 + '@jimp/plugin-mask': 1.6.0 + '@jimp/plugin-print': 1.6.0 + '@jimp/plugin-quantize': 1.6.0 + '@jimp/plugin-resize': 1.6.0 + '@jimp/plugin-rotate': 1.6.0 + '@jimp/plugin-threshold': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + + jpeg-js@0.4.4: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + lines-and-columns@1.2.4: {} + + lit-element@4.2.2: + dependencies: + '@lit-labs/ssr-dom-shim': 1.5.1 + '@lit/reactive-element': 2.1.2 + lit-html: 3.3.2 + + lit-html@3.3.2: + dependencies: + '@types/trusted-types': 2.0.7 + + lit@3.3.2: + dependencies: + '@lit/reactive-element': 2.1.2 + lit-element: 4.2.2 + lit-html: 3.3.2 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + lodash.clonedeep@4.5.0: {} + + longest-streak@3.1.0: {} + + lower-case@1.1.4: {} + + lowercase-keys@3.0.0: {} + + lru-cache@11.3.2: {} + + lru-cache@7.18.3: {} + + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + + make-error-cause@2.3.0: + dependencies: + make-error: 1.3.6 + + make-error@1.3.6: {} + + markdown-table@3.0.4: {} + + matcher@5.0.0: + dependencies: + escape-string-regexp: 5.0.0 + + math-intrinsics@1.1.0: {} + + maxmind@5.0.6: + dependencies: + mmdb-lib: 3.0.2 + tiny-lru: 13.0.0 + + mdast-util-find-and-replace@3.0.2: + dependencies: + '@types/mdast': 4.0.4 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + mdast-util-from-markdown@2.0.3: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-frontmatter@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + escape-string-regexp: 5.0.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + micromark-extension-frontmatter: 2.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-autolink-literal@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.2 + micromark-util-character: 2.1.1 + + mdast-util-gfm-footnote@2.1.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + micromark-util-normalize-identifier: 2.0.1 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-strikethrough@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-table@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-task-list-item@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm@3.1.0: + dependencies: + mdast-util-from-markdown: 2.0.3 + mdast-util-gfm-autolink-literal: 2.0.1 + mdast-util-gfm-footnote: 2.1.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.1 + + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + + mdast-util-to-markdown@2.1.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + memory-pager@1.5.0: {} + + micromark-core-commonmark@2.0.3: + dependencies: + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-frontmatter@2.0.0: + dependencies: + fault: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-autolink-literal@2.1.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-footnote@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-strikethrough@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-table@2.1.1: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-tagfilter@2.0.0: + dependencies: + micromark-util-types: 2.0.2 + + micromark-extension-gfm-task-list-item@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm@3.0.0: + dependencies: + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.1 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.1.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.3.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@2.0.1: {} + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.2 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + + micromark@4.0.2: + dependencies: + '@types/debug': 4.1.13 + debug: 4.4.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + transitivePeerDependencies: + - supports-color + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@3.0.0: {} + + mime@4.1.0: {} + + mimic-response@3.1.0: {} + + mimic-response@4.0.0: {} + + mingo@7.2.1: {} + + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.5 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.13 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.0.3 + + minimist@1.2.8: {} + + minipass@7.1.3: {} + + mitt@3.0.1: {} + + mmdb-lib@3.0.2: {} + + mongodb-connection-string-url@3.0.2: + dependencies: + '@types/whatwg-url': 11.0.5 + whatwg-url: 14.2.0 + + mongodb-connection-string-url@7.0.1: + dependencies: + '@types/whatwg-url': 13.0.0 + whatwg-url: 14.2.0 + + mongodb-memory-server-core@11.0.1(socks@2.8.7): + dependencies: + async-mutex: 0.5.0 + camelcase: 6.3.0 + debug: 4.4.3 + find-cache-dir: 3.3.2 + follow-redirects: 1.15.11(debug@4.4.3) + https-proxy-agent: 7.0.6 + mongodb: 7.1.1(socks@2.8.7) + new-find-package-json: 2.0.0 + semver: 7.7.4 + tar-stream: 3.1.8 + tslib: 2.8.1 + yauzl: 3.3.0 + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - bare-abort-controller + - bare-buffer + - gcp-metadata + - kerberos + - mongodb-client-encryption + - react-native-b4a + - snappy + - socks + - supports-color + + mongodb-memory-server@11.0.1(socks@2.8.7): + dependencies: + mongodb-memory-server-core: 11.0.1(socks@2.8.7) + tslib: 2.8.1 + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - bare-abort-controller + - bare-buffer + - gcp-metadata + - kerberos + - mongodb-client-encryption + - react-native-b4a + - snappy + - socks + - supports-color + + mongodb@6.21.0(socks@2.8.7): + dependencies: + '@mongodb-js/saslprep': 1.4.6 + bson: 6.10.4 + mongodb-connection-string-url: 3.0.2 + optionalDependencies: + socks: 2.8.7 + + mongodb@7.1.1(socks@2.8.7): + dependencies: + '@mongodb-js/saslprep': 1.4.6 + bson: 7.2.0 + mongodb-connection-string-url: 7.0.1 + optionalDependencies: + socks: 2.8.7 + + ms@2.1.3: {} + + mute-stream@1.0.0: {} + + nanoid@4.0.2: {} + + netmask@2.1.0: {} + + new-find-package-json@2.0.0: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + no-case@2.3.2: + dependencies: + lower-case: 1.1.4 + + node-forge@1.4.0: {} + + normalize-url@8.1.1: {} + + object-keys@1.1.1: {} + + oblivious-set@2.0.0: {} + + observable-fns@0.6.1: {} + + omggif@1.0.10: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + os-tmpdir@1.0.2: {} + + p-cancelable@3.0.0: {} + + p-finally@1.0.0: {} + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-queue@6.6.2: + dependencies: + eventemitter3: 4.0.7 + p-timeout: 3.2.0 + + p-timeout@3.2.0: + dependencies: + p-finally: 1.0.0 + + p-try@2.2.0: {} + + pac-proxy-agent@7.2.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.4 + debug: 4.4.3 + get-uri: 6.0.5 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.1.0 + + package-json-from-dist@1.0.1: {} + + package-json@8.1.1: + dependencies: + got: 12.6.1 + registry-auth-token: 5.1.1 + registry-url: 6.0.1 + semver: 7.7.4 + + pako@1.0.11: {} + + param-case@2.1.1: + dependencies: + no-case: 2.3.2 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-bmfont-ascii@1.0.6: {} + + parse-bmfont-binary@1.0.6: {} + + parse-bmfont-xml@1.1.6: + dependencies: + xml-parse-from-string: 1.0.1 + xml2js: 0.5.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.0 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-ms@4.0.0: {} + + path-exists@4.0.0: {} + + path-expression-matcher@1.4.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-scurry@2.0.2: + dependencies: + lru-cache: 11.3.2 + minipass: 7.1.3 + + path-to-regexp@8.4.2: {} + + pdf-lib@1.17.1: + dependencies: + '@pdf-lib/standard-fonts': 1.0.0 + '@pdf-lib/upng': 1.0.1 + pako: 1.0.11 + tslib: 1.14.1 + + pdf2json@4.0.2: {} + + peek-readable@4.1.0: {} + + peek-readable@5.4.2: {} + + pend@1.2.0: {} + + picocolors@1.1.1: {} + + picomatch@4.0.4: {} + + pixelmatch@5.3.0: + dependencies: + pngjs: 6.0.0 + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + pngjs@6.0.0: {} + + pngjs@7.0.0: {} + + pretty-ms@9.3.0: + dependencies: + parse-ms: 4.0.0 + + process@0.11.10: {} + + progress@2.0.3: {} + + property-information@7.1.0: {} + + proto-list@1.2.4: {} + + proxy-agent@6.5.0: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 7.18.3 + pac-proxy-agent: 7.2.0 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + + proxy-from-env@2.1.0: {} + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + punycode@2.3.1: {} + + puppeteer-core@24.40.0: + dependencies: + '@puppeteer/browsers': 2.13.0 + chromium-bidi: 14.0.0(devtools-protocol@0.0.1581282) + debug: 4.4.3 + devtools-protocol: 0.0.1581282 + typed-query-selector: 2.12.1 + webdriver-bidi-protocol: 0.4.1 + ws: 8.20.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - bufferutil + - react-native-b4a + - supports-color + - utf-8-validate + + puppeteer@24.40.0(typescript@6.0.2): + dependencies: + '@puppeteer/browsers': 2.13.0 + chromium-bidi: 14.0.0(devtools-protocol@0.0.1581282) + cosmiconfig: 9.0.1(typescript@6.0.2) + devtools-protocol: 0.0.1581282 + puppeteer-core: 24.40.0 + typed-query-selector: 2.12.1 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - bufferutil + - react-native-b4a + - supports-color + - typescript + - utf-8-validate + + pvtsutils@1.3.6: + dependencies: + tslib: 2.8.1 + + pvutils@1.1.5: {} + + quick-lru@5.1.1: {} + + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + readable-web-to-node-stream@3.0.4: + dependencies: + readable-stream: 4.7.0 + + readdirp@5.0.0: {} + + reflect-metadata@0.2.2: {} + + registry-auth-token@5.1.1: + dependencies: + '@pnpm/npm-conf': 3.0.2 + + registry-url@6.0.1: + dependencies: + rc: 1.2.8 + + relateurl@0.2.7: {} + + remark-frontmatter@5.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-frontmatter: 2.0.1 + micromark-extension-frontmatter: 2.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-gfm@4.0.1: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-gfm: 3.1.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-html@16.0.1: + dependencies: + '@types/mdast': 4.0.4 + hast-util-sanitize: 5.0.2 + hast-util-to-html: 9.0.5 + mdast-util-to-hast: 13.2.1 + unified: 11.0.5 + + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + micromark-util-types: 2.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-stringify@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.2 + unified: 11.0.5 + + require-directory@2.1.1: {} + + resolve-alpn@1.2.1: {} + + resolve-from@4.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + responselike@3.0.0: + dependencies: + lowercase-keys: 3.0.0 + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rolldown@1.0.0-rc.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2): + dependencies: + '@oxc-project/types': 0.122.0 + '@rolldown/pluginutils': 1.0.0-rc.11 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.11 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.11 + '@rolldown/binding-darwin-x64': 1.0.0-rc.11 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.11 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.11 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.11 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.11 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.11 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.11 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.11 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + run-async@3.0.0: {} + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + sax@1.6.0: {} + + semver@6.3.1: {} + + semver@7.7.4: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + sharp@0.34.5: + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.7.4 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + simple-xml-to-json@1.2.7: {} + + smart-buffer@4.2.0: {} + + socks-proxy-agent@8.0.5: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + socks: 2.8.7 + transitivePeerDependencies: + - supports-color + + socks@2.8.7: + dependencies: + ip-address: 10.1.0 + smart-buffer: 4.2.0 + + source-map@0.6.1: {} + + space-separated-tokens@2.0.2: {} + + sparse-bitfield@3.0.3: + dependencies: + memory-pager: 1.5.0 + + spawn-wrap@2.0.0: + dependencies: + foreground-child: 2.0.0 + is-windows: 1.0.2 + make-dir: 3.1.0 + rimraf: 3.0.2 + signal-exit: 3.0.7 + which: 2.0.2 + + sprintf-js@1.0.3: {} + + streamx@2.25.0: + dependencies: + events-universal: 1.0.1 + fast-fifo: 1.3.2 + text-decoder: 1.2.7 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-json-comments@2.0.1: {} + + strnum@2.2.3: {} + + strtok3@10.3.5: + dependencies: + '@tokenizer/token': 0.3.0 + + strtok3@6.3.0: + dependencies: + '@tokenizer/token': 0.3.0 + peek-readable: 4.1.0 + + strtok3@9.1.1: + dependencies: + '@tokenizer/token': 0.3.0 + peek-readable: 5.4.2 + + sweet-scroll@4.0.0: {} + + symbol-tree@3.2.4: {} + + tagged-tag@1.0.0: {} + + tar-fs@3.1.2: + dependencies: + pump: 3.0.4 + tar-stream: 3.1.8 + optionalDependencies: + bare-fs: 4.6.0 + bare-path: 3.0.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + + tar-stream@3.1.8: + dependencies: + b4a: 1.8.0 + bare-fs: 4.6.0 + fast-fifo: 1.3.2 + streamx: 2.25.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + + teex@1.0.1: + dependencies: + streamx: 2.25.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + text-decoder@1.2.7: + dependencies: + b4a: 1.8.0 + transitivePeerDependencies: + - react-native-b4a + + threads@1.7.0: + dependencies: + callsites: 3.1.0 + debug: 4.4.3 + is-observable: 2.1.0 + observable-fns: 0.6.1 + optionalDependencies: + tiny-worker: 2.3.0 + transitivePeerDependencies: + - supports-color + + through2@4.0.2: + dependencies: + readable-stream: 3.6.2 + + tiny-lru@13.0.0: {} + + tiny-worker@2.3.0: + dependencies: + esm: 3.2.25 + + tinycolor2@1.6.0: {} + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + token-types@4.2.1: + dependencies: + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + + token-types@6.1.2: + dependencies: + '@borewit/text-codec': 0.2.2 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + + tree-kill@1.2.2: {} + + trim-lines@3.0.1: {} + + trough@2.2.0: {} + + tslib@1.14.1: {} + + tslib@2.8.1: {} + + tsx@4.21.0: + dependencies: + esbuild: 0.27.7 + get-tsconfig: 4.13.7 + optionalDependencies: + fsevents: 2.3.3 + + tsyringe@4.10.0: + dependencies: + tslib: 1.14.1 + + turndown-plugin-gfm@1.0.2: {} + + turndown@7.2.4: + dependencies: + '@mixmark-io/domino': 2.2.0 + + type-fest@0.21.3: {} + + type-fest@4.41.0: {} + + type-fest@5.5.0: + dependencies: + tagged-tag: 1.0.0 + + typed-query-selector@2.12.1: {} + + typescript@6.0.2: {} + + uglify-js@3.19.3: {} + + uint8array-extras@1.5.0: {} + + undici-types@6.21.0: {} + + undici-types@7.18.2: {} + + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + universalify@2.0.1: {} + + unload@2.4.1: {} + + upper-case@1.1.3: {} + + utif2@4.1.0: + dependencies: + pako: 1.0.11 + + util-deprecate@1.0.2: {} + + uuid@9.0.1: {} + + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + + webdriver-bidi-protocol@0.4.1: {} + + webidl-conversions@7.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@6.0.1: + dependencies: + isexe: 4.0.0 + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + ws@8.20.0: {} + + xml-parse-from-string@1.0.1: {} + + xml2js@0.5.0: + dependencies: + sax: 1.6.0 + xmlbuilder: 11.0.1 + + xmlbuilder@11.0.1: {} + + y18n@5.0.8: {} + + yargs-parser@21.1.1: {} + + yargs-parser@22.0.0: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + + yauzl@3.3.0: + dependencies: + buffer-crc32: 0.2.13 + pend: 1.2.0 + + yoctocolors-cjs@2.1.3: {} + + zod@3.25.76: {} + + zwitch@2.0.4: {} diff --git a/readme.hints.md b/readme.hints.md new file mode 100644 index 0000000..e2a6fbe --- /dev/null +++ b/readme.hints.md @@ -0,0 +1,26 @@ +# readme.hints.md + +Internal development notes for `@push.rocks/smartmigration`. This file is not published to npm. + +## Architecture + +- The ledger is the source of truth. Two backends: mongo (via smartdata `EasyStore`) and S3 (via `bucket.fastPut`/`fastGet`). +- Step execution is **sequential and registration-ordered**. The `from`/`to` fields exist for chain validation, not for DAG resolution. +- Drivers (`mongodb.Db`, `S3Client`) are exposed via `ctx`, not wrapped. smartmigration writes no SQL or S3 wrappers of its own. + +## Locking caveats + +- The mongo lock uses a read-modify-write pattern over `EasyStore` (which writes the entire document each time). This is a last-writer-wins CAS, not a true atomic CAS. It's adequate for v1; v2 may move to `findOneAndUpdate` against the underlying mongo collection. +- The S3 lock is best-effort (S3 has no conditional writes without versioning). S3-only deployments should not run multiple instances against the same ledger without external coordination. + +## Why EasyStore (and not a custom collection)? + +- Already exists, lazy collection setup, single-document storage that fits the entire ledger naturally. +- Avoids polluting the user's DB with smartmigration-internal classes. +- See `/mnt/data/lossless/push.rocks/smartdata/ts/classes.easystore.ts` for the implementation. + +## Testing notes + +- Use `@push.rocks/smartmongo`'s `SmartMongo.createAndStart()` for an in-memory replica set. +- After `createAndStart()`, call `getMongoDescriptor()` and feed the result to `new SmartdataDb(...)`. +- Always call `db.close()` and `smartMongo.stop()` in test cleanup. diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..275cc6c --- /dev/null +++ b/readme.md @@ -0,0 +1,376 @@ +# @push.rocks/smartmigration + +A unified migration runner for MongoDB (via [@push.rocks/smartdata](https://code.foss.global/push.rocks/smartdata)) and S3 (via [@push.rocks/smartbucket](https://code.foss.global/push.rocks/smartbucket)) — designed to be invoked at SaaS app startup. + +## Installation + +```bash +pnpm add @push.rocks/smartmigration +# plus whichever resources you need +pnpm add @push.rocks/smartdata @push.rocks/smartbucket +``` + +`@push.rocks/smartdata` and `@push.rocks/smartbucket` are declared as **optional peer dependencies** — install whichever ones your migrations actually touch. + +## Issue Reporting and Security + +Report bugs and security issues at [community.foss.global](https://community.foss.global). + +## What is smartmigration? + +`smartmigration` is the missing piece for SaaS apps in the push.rocks ecosystem: a deterministic, idempotent way to evolve persistent data in lockstep with code releases. You define a chain of migration steps with `from`/`to` semver versions, hand the runner your `SmartdataDb` and/or `Bucket`, and call `run()` from your app's startup path. The runner figures out which steps need to execute, runs them sequentially, and stamps progress into a ledger so subsequent boots are fast no-ops. + +### Key features + +| Feature | Description | +|---|---| +| **Builder-style API** | Fluent step definition: `step('id').from('1.0.0').to('1.1.0').up(handler)` | +| **Unified mongo + S3** | A single semver represents your combined data version. One step can touch both. | +| **Drivers exposed via context** | `ctx.db`, `ctx.mongo`, `ctx.bucket`, `ctx.s3` — write any operation you can write directly | +| **Idempotent** | `run()` is a no-op when data is at `targetVersion`. Costs one ledger read on the happy path. | +| **Resumable** | Mark a step `.resumable()` and it gets `ctx.checkpoint.read/write/clear` for restartable bulk operations | +| **Lockable** | Mongo-backed lock with TTL serializes concurrent SaaS instances — safe for rolling deploys | +| **Fresh-install fast path** | Configure `freshInstallVersion` to skip migrations on a brand-new database | +| **Dry-run** | `dryRun: true` or `.plan()` returns the execution plan without writing anything | +| **Structured errors** | All failures throw `SmartMigrationError` with a stable `code` field for branching | + +## Quick start + +```ts +import { SmartdataDb } from '@push.rocks/smartdata'; +import { SmartBucket } from '@push.rocks/smartbucket'; +import { SmartMigration } from '@push.rocks/smartmigration'; +import { commitinfo } from './00_commitinfo_data.js'; + +// 1. set up your resources as you normally would +const db = new SmartdataDb({ + mongoDbUrl: process.env.MONGODB_URL!, + mongoDbName: 'myapp', +}); +await db.init(); + +const sb = new SmartBucket({ + accessKey: process.env.S3_ACCESSKEY!, + accessSecret: process.env.S3_SECRETKEY!, + endpoint: process.env.S3_ENDPOINT!, + region: 'us-east-1', +}); +const bucket = await sb.getBucketByName('myapp-uploads'); + +// 2. construct the runner with your app's target version +const migration = new SmartMigration({ + targetVersion: commitinfo.version, + db, + bucket, +}); + +// 3. register migrations in execution order, with from/to validating the chain +migration + .step('lowercase-emails') + .from('1.0.0').to('1.1.0') + .description('Lowercase all user emails') + .up(async (ctx) => { + await ctx.mongo!.collection('users').updateMany( + {}, + [{ $set: { email: { $toLower: '$email' } } }], + ); + }) + .step('reorganize-uploads') + .from('1.1.0').to('2.0.0') + .description('Move uploads/ to media/') + .resumable() + .up(async (ctx) => { + const cursor = ctx.bucket!.createCursor('uploads/'); + const startToken = await ctx.checkpoint!.read('cursorToken'); + if (startToken) cursor.setToken(startToken); + while (await cursor.hasMore()) { + for (const key of (await cursor.next()) ?? []) { + await ctx.bucket!.fastMove({ + sourcePath: key, + destinationPath: 'media/' + key.slice('uploads/'.length), + overwrite: true, + }); + } + await ctx.checkpoint!.write('cursorToken', cursor.getToken()); + } + }); + +// 4. run on startup — fast no-op once the data is at targetVersion +const result = await migration.run(); +console.log(`smartmigration: ${result.currentVersionBefore ?? 'fresh'} → ${result.currentVersionAfter} (${result.stepsApplied.length} steps in ${result.totalDurationMs}ms)`); +``` + +## Core concepts + +### The data version + +A single semver string represents the combined state of your mongo and S3 data. It is **not** the same as your app version (though you usually want them to match): the app version is what's running, the data version is what's on disk. The runner's job is to bring the data version up to the app version. + +### Steps and the chain + +Each migration is a `step` with: + +- A unique **id** (string) — used as the ledger key +- A **`from`** semver — the data version this step expects to start from +- A **`to`** semver — the data version this step produces +- An **`up`** handler — the actual migration logic +- An optional **description**, **resumable** flag + +Steps execute in **registration order**. The runner validates that the chain is contiguous: `step[N].to === step[N+1].from`. This catches gaps and overlaps at definition time, before any handler runs. + +### The ledger + +The ledger is the source of truth for "what data version are we at, what steps have been applied, who holds the lock right now." It is persisted in one of two backends: + +- **`mongo` (default when `db` is provided)** — backed by smartdata's `EasyStore`, stored as a single document. Lock semantics work safely across multiple SaaS instances. **Recommended.** +- **`s3` (default when only `bucket` is provided)** — a single JSON object at `/.smartmigration/.json`. Lock is best-effort because S3 has no atomic CAS without additional infrastructure; do not use for multi-instance deployments without external coordination. + +If you pass both `db` and `bucket`, mongo is used. + +### The migration context + +Each `up` handler receives a `IMigrationContext` with: + +```ts +interface IMigrationContext { + db?: SmartdataDb; // high-level smartdata + bucket?: Bucket; // high-level smartbucket Bucket + mongo?: mongodb.Db; // raw mongo Db (db.mongoDb) + s3?: S3Client; // raw AWS SDK v3 S3Client + step: { id, fromVersion, toVersion, description?, isResumable }; + log: Smartlog; + isDryRun: boolean; + checkpoint?: IMigrationCheckpoint; // only when step is .resumable() + startSession(): mongodb.ClientSession; // throws if no db +} +``` + +Use whichever level fits your migration: +- **High-level** (`ctx.db`, `ctx.bucket`) for working with smartdata models / smartbucket files +- **Raw drivers** (`ctx.mongo`, `ctx.s3`) for any operation smartdata/smartbucket don't wrap (renameCollection, dropIndex, S3 lifecycle policies, etc.) +- **`startSession()`** for transactional mongo migrations + +## Common use cases + +### Mongo schema rename + +```ts +migration + .step('rename-user-email-field') + .from('1.0.0').to('1.1.0') + .up(async (ctx) => { + await ctx.mongo!.collection('users').updateMany( + { emailAddress: { $exists: true } }, + { $rename: { emailAddress: 'email' } }, + ); + }); +``` + +### Backfilling a derived field with a transaction + +```ts +migration + .step('backfill-account-tier') + .from('1.5.0').to('2.0.0') + .up(async (ctx) => { + const session = ctx.startSession(); + try { + await session.withTransaction(async () => { + const users = ctx.mongo!.collection('users'); + await users.updateMany( + { tier: { $exists: false }, plan: 'free' }, + { $set: { tier: 'free' } }, + { session }, + ); + await users.updateMany( + { tier: { $exists: false }, plan: { $in: ['pro', 'enterprise'] } }, + { $set: { tier: 'paid' } }, + { session }, + ); + }); + } finally { + await session.endSession(); + } + }); +``` + +### Resumable S3 reprefix + +```ts +migration + .step('move-attachments') + .from('2.0.0').to('2.1.0') + .resumable() + .up(async (ctx) => { + const cursor = ctx.bucket!.createCursor('attachments/legacy/', { pageSize: 200 }); + const start = await ctx.checkpoint!.read('cursor'); + if (start) cursor.setToken(start); + while (await cursor.hasMore()) { + const batch = (await cursor.next()) ?? []; + for (const key of batch) { + await ctx.bucket!.fastMove({ + sourcePath: key, + destinationPath: 'attachments/' + key.slice('attachments/legacy/'.length), + overwrite: true, + }); + } + await ctx.checkpoint!.write('cursor', cursor.getToken()); + } + }); +``` + +If the process crashes mid-migration, the next call to `run()` will resume from the last persisted cursor token. + +### Mongo + S3 in lockstep + +```ts +migration + .step('split-avatars-out-of-users') + .from('2.1.0').to('2.5.0') + .up(async (ctx) => { + // 1. for every user with an inline avatarBytes field, write the bytes to S3 + const users = ctx.mongo!.collection('users'); + const cursor = users.find({ avatarBytes: { $exists: true } }); + for await (const user of cursor) { + const buf = Buffer.from(user.avatarBytes.buffer); + await ctx.bucket!.fastPut({ + path: `avatars/${user._id}.bin`, + contents: buf, + overwrite: true, + }); + await users.updateOne( + { _id: user._id }, + { $set: { avatarKey: `avatars/${user._id}.bin` }, $unset: { avatarBytes: '' } }, + ); + } + }); +``` + +### Fresh-install fast path + +```ts +const migration = new SmartMigration({ + targetVersion: '5.0.0', + db, + freshInstallVersion: '5.0.0', // brand-new DB jumps straight to 5.0.0 +}); +// ... register your full chain of steps ... +await migration.run(); // for a fresh DB, runs zero steps and stamps version 5.0.0 +``` + +### Dry run / planning + +```ts +const planned = await migration.plan(); +console.log(`would apply ${planned.stepsSkipped.length} steps:`, + planned.stepsSkipped.map((s) => `${s.id}(${s.fromVersion}→${s.toVersion})`).join(' → ')); + +// or — same thing, via dryRun option +const m = new SmartMigration({ targetVersion: '2.0.0', db, dryRun: true }); +// ... +const result = await m.run(); // returns plan, doesn't write +``` + +## API reference + +### `new SmartMigration(options: ISmartMigrationOptions)` + +| Option | Type | Default | Description | +|---|---|---|---| +| `targetVersion` | `string` | — (required) | Semver representing the data version this code expects | +| `db` | `SmartdataDb` | undefined | Required if any step uses `ctx.db`/`ctx.mongo` or for the mongo ledger | +| `bucket` | `Bucket` | undefined | Required if any step uses `ctx.bucket`/`ctx.s3` or for the S3 ledger | +| `ledgerName` | `string` | `"smartmigration"` | Logical name; lets multiple migrations coexist on the same db/bucket | +| `ledgerBackend` | `'mongo'` \| `'s3'` | mongo if db, else s3 | Where to persist the ledger | +| `freshInstallVersion` | `string` | undefined | When the resource is empty, jump straight to this version | +| `lockWaitMs` | `number` | `60_000` | How long to wait for a stale lock from another instance | +| `lockTtlMs` | `number` | `600_000` | How long this instance's own lock auto-expires after | +| `dryRun` | `boolean` | `false` | If true, `run()` returns the plan without executing or locking | +| `logger` | `Smartlog` | module logger | Custom logger; defaults to a Smartlog with a local destination | + +The constructor throws `SmartMigrationError` with one of these `code`s on bad input: +- `INVALID_OPTIONS` — options object missing +- `MISSING_TARGET_VERSION` — `targetVersion` not set +- `INVALID_VERSION` — `targetVersion` is not a valid semver +- `NO_RESOURCES` — neither `db` nor `bucket` provided +- `LEDGER_BACKEND_MISMATCH` — explicit `ledgerBackend` doesn't match the resources you provided + +### `migration.step(id: string).from(v).to(v).[description(t)].[resumable()].up(handler)` + +The step builder. `.from()`, `.to()`, and `.up()` are required; `.description()` and `.resumable()` are optional. `.up()` is the terminal call: it commits the step to the parent runner and returns the runner so you can chain `.step('next')`. + +### `migration.run(): Promise` + +The startup entry point. Acquires a lock, computes the plan, executes pending steps in order, and releases the lock. Returns: + +```ts +interface IMigrationRunResult { + currentVersionBefore: string | null; + currentVersionAfter: string; + targetVersion: string; + wasUpToDate: boolean; // true if no steps ran + wasFreshInstall: boolean; // true if freshInstallVersion was used + stepsApplied: IMigrationStepResult[]; + stepsSkipped: IMigrationStepResult[]; + totalDurationMs: number; +} +``` + +Throws `SmartMigrationError` with these `code`s: +- `LOCK_TIMEOUT` — could not acquire lock within `lockWaitMs` +- `STEP_FAILED` — a step's handler threw; the failure is persisted to the ledger +- `CHAIN_*`, `DUPLICATE_STEP_ID`, `NON_INCREASING_STEP`, `TARGET_NOT_REACHABLE`, `DOWNGRADE_NOT_SUPPORTED` — chain validation / planning errors + +### `migration.plan(): Promise` + +Same as `run()` but does not acquire the lock or execute anything. Useful for `--dry-run` style probes in CI. + +### `migration.getCurrentVersion(): Promise` + +Returns the current data version from the ledger, or `null` if the ledger has never been initialized. + +## Troubleshooting + +### `LOCK_TIMEOUT` on every startup + +Another instance crashed while holding the lock. Wait for `lockTtlMs` (default 10 minutes) for the lock to expire, or manually clear the `lock` field on the ledger document. + +### `CHAIN_GAP` at startup + +Two adjacent steps have mismatched versions: `step[N].to !== step[N+1].from`. Steps must form a contiguous chain in registration order. Fix the version on the offending step. + +### `CHAIN_NOT_AT_CURRENT` + +The ledger says the data is at version X, but no registered step starts at X. This usually happens when you delete a step that has already been applied to production data. Either keep the step or manually update the ledger's `currentVersion`. + +### S3-only deployments and concurrent instances + +The S3 ledger's lock is best-effort. If you run multiple SaaS instances against the same S3 bucket, use external coordination (e.g. Redis lock, leader election) before calling `run()`. The mongo backend has no such limitation. + +## Best practices + +1. **Prefer idempotent migrations.** Even with the lock, machines crash, networks partition, and migrations should be safe to re-run. Use `$set` over `$inc`, check existence before insert, etc. +2. **Use `.resumable()` for any step that processes more than a few hundred records.** Crashes happen; resumability avoids redoing work. +3. **Use transactions for multi-collection mongo migrations** via `ctx.startSession()` + `session.withTransaction()`. +4. **Don't mix S3 and Mongo writes inside a single conceptual operation** — S3 has no transactions, so design migrations so each S3 write is observably idempotent on its own. +5. **Keep the `targetVersion` linked to your app's package.json `version`** via the autocreated `00_commitinfo_data.ts`. That way every release automatically signals the data version it expects. +6. **Freeze applied migrations in source control** — don't edit a step that has been applied to production data, even if the new version is "more correct." Add a new step instead. + +## License and Legal Information + +This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. + +**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file. + +### Trademarks + +This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH. + +### Company Information + +Task Venture Capital GmbH +Registered at District court Bremen HRB 35230 HB, Germany + +For any legal inquiries or if you require further information, please contact us via email at hello@task.vc. + +By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works. diff --git a/readme.plan.md b/readme.plan.md new file mode 100644 index 0000000..3161348 --- /dev/null +++ b/readme.plan.md @@ -0,0 +1,590 @@ +# @push.rocks/smartmigration — Plan + +> reread /home/philkunz/.claude/CLAUDE.md before working from this plan + +## Context + +`@push.rocks/smartmigration` is a brand-new module that does not yet exist (the directory at `/mnt/data/lossless/push.rocks/smartmigration` is empty except for `.git/`). Its purpose is to **unify migrations across MongoDB and S3** with a small, builder-style API designed to be invoked on **SaaS app startup**: it inspects the current data version, computes the sequential chain of steps required to reach the app's target version, executes them safely, and stamps progress into a ledger so re-runs are no-ops. + +**Why this needs to exist.** Across the push.rocks ecosystem (`smartdata`, `smartbucket`, `smartdb`, `mongodump`, `smartversion`) there is no migration tooling at all — a search for `migration|migrate|schemaVersion` across the relevant `ts/` trees returned zero hits. SaaS apps that ship multiple deploys per week need a deterministic way to evolve persistent state in lockstep with code, and they need it to "just work" when the app boots — not as a separate operator-driven process. Both `smartdata` and `smartbucket` already expose their underlying drivers (`SmartdataDb.mongoDb` / `SmartdataDb.mongoDbClient`, `SmartBucket.storageClient`), so smartmigration only needs to provide the **runner, ledger, and context plumbing** — it does not need to wrap mongo or S3 itself. + +**Intended outcome.** A SaaS app can do this at startup and forget about it: + +```ts +import { SmartMigration } from '@push.rocks/smartmigration'; +import { commitinfo } from './00_commitinfo_data.js'; + +const migration = new SmartMigration({ + targetVersion: commitinfo.version, // app version drives data version + db, // optional SmartdataDb + bucket, // optional SmartBucket Bucket +}); + +migration + .step('lowercase-emails') + .from('1.0.0').to('1.1.0') + .description('Lowercase all user emails') + .up(async (ctx) => { + await ctx.mongo.collection('users').updateMany( + {}, + [{ $set: { email: { $toLower: '$email' } } }], + ); + }) + .step('reorganize-uploads') + .from('1.1.0').to('2.0.0') + .description('Move uploads/ to media/') + .resumable() + .up(async (ctx) => { + const cursor = ctx.bucket.createCursor('uploads/'); + let token = await ctx.checkpoint.read('cursorToken'); + if (token) cursor.setToken(token); + while (await cursor.hasMore()) { + for (const key of await cursor.next()) { + await ctx.bucket.fastMove({ + sourcePath: key, + destinationPath: 'media/' + key.slice('uploads/'.length), + }); + } + await ctx.checkpoint.write('cursorToken', cursor.getToken()); + } + }); + +await migration.run(); // fast no-op if already at target +``` + +--- + +## Confirmed design decisions + +These were chosen during planning and are locked in: + +- **Step ordering:** registration order, with from/to validation. Steps execute in the order they were registered. The runner verifies each step's `from` matches the previous step's `to` (or the current ledger version) and errors out on gaps/overlaps. No DAG / topological sort. +- **Rollback:** **up-only for v1.** No `.down()` API. Forward-only migrations are simpler and safer; users restore from backup if a migration goes wrong. May be revisited in v2. + +--- + +## Design at a glance + +### Core principles + +1. **One unified data version.** A single semver string represents the combined state of mongo + S3. Steps transition `from` → `to`. (Tracking mongo and S3 versions independently is rejected because it explodes step typing for marginal value — the app's data version is what users actually reason about.) +2. **Builder-style step definition, single options object for the runner.** The constructor takes a plain options object (`new SmartMigration({...})`); steps are added via a fluent chain (`migration.step('id').from('1.0.0').to('1.1.0').up(async ctx => {...})`). The chain returns the parent `SmartMigration` after `.up()` so multiple steps chain naturally. +3. **Drivers are exposed via context, not wrapped.** Migration `up` functions receive a `MigrationContext` that hands them both high-level (`ctx.db`, `ctx.bucket`) and raw (`ctx.mongo`, `ctx.s3`) handles. smartmigration writes no SQL or S3 wrappers of its own. +4. **Idempotent, restartable, lockable.** Re-running `migration.run()` on already-applied data is a no-op. Steps marked `.resumable()` get a per-step checkpoint store. A mongo-backed lock prevents concurrent SaaS instances from racing on the same migration. +5. **Fast on the happy path.** When `currentVersion === targetVersion`, `run()` performs **one** read against the ledger and returns. No driver calls beyond that. +6. **Order is registration order; from/to is for validation.** Steps execute in the order they were registered. The runner verifies that each step's `from` matches the previous step's `to` (or the current ledger version) and errors out on gaps/overlaps. This avoids the complexity of computing a DAG path while still catching mistakes. + +### Public API surface + +```ts +// ts/index.ts +export { SmartMigration } from './classes.smartmigration.js'; +export type { + ISmartMigrationOptions, + IMigrationStepDefinition, + IMigrationContext, + IMigrationCheckpoint, + IMigrationRunResult, + IMigrationStepResult, + IMigrationLedgerEntry, +} from './interfaces.js'; +export type { TMigrationStatus, TLedgerBackend } from './types.js'; +export { SmartMigrationError } from './classes.smartmigration.js'; +``` + +### `ISmartMigrationOptions` + +```ts +export interface ISmartMigrationOptions { + /** Target version for the data. Typically the app's package.json version. */ + targetVersion: string; + + /** Optional smartdata instance. Required if any step uses ctx.db / ctx.mongo. */ + db?: plugins.smartdata.SmartdataDb; + + /** Optional smartbucket Bucket. Required if any step uses ctx.bucket / ctx.s3. */ + bucket?: plugins.smartbucket.Bucket; + + /** Logical name for this migration ledger. Defaults to "smartmigration". */ + ledgerName?: string; + + /** Where to persist the ledger. Defaults to "mongo" if db provided, otherwise "s3". */ + ledgerBackend?: TLedgerBackend; // 'mongo' | 's3' + + /** + * For a fresh install (no ledger AND no app data), jump straight to this version + * instead of running every step from the earliest. Defaults to undefined, + * which means "run every step from earliest from-version". + */ + freshInstallVersion?: string; + + /** How long (ms) to wait for a stale lock from another instance. Default 60_000. */ + lockWaitMs?: number; + + /** How long (ms) before this instance's own lock auto-expires. Default 600_000. */ + lockTtlMs?: number; + + /** If true, run() returns the plan without executing anything. Default false. */ + dryRun?: boolean; + + /** Custom logger. Defaults to module logger. */ + logger?: plugins.smartlog.Smartlog; +} +``` + +### `IMigrationContext` + +```ts +export interface IMigrationContext { + // High-level + db?: plugins.smartdata.SmartdataDb; + bucket?: plugins.smartbucket.Bucket; + + // Raw drivers + mongo?: plugins.mongodb.Db; // db.mongoDb + s3?: plugins.awsSdk.S3Client; // bucket.parentSmartBucket.storageClient + + // Step metadata + step: { + id: string; + fromVersion: string; + toVersion: string; + description?: string; + isResumable: boolean; + }; + + // Convenience + log: plugins.smartlog.Smartlog; + isDryRun: boolean; + + /** Only present when step.isResumable === true. */ + checkpoint?: IMigrationCheckpoint; + + /** Convenience for transactional mongo migrations. Throws if no db configured. */ + startSession(): plugins.mongodb.ClientSession; +} + +export interface IMigrationCheckpoint { + read(key: string): Promise; + write(key: string, value: T): Promise; + clear(): Promise; +} +``` + +### `MigrationStepBuilder` (chained, terminal `.up()` returns parent `SmartMigration`) + +```ts +class MigrationStepBuilder { + from(version: string): this; + to(version: string): this; + description(text: string): this; + resumable(): this; // enables ctx.checkpoint + up(handler: (ctx: IMigrationContext) => Promise): SmartMigration; +} +``` + +### `SmartMigration` + +```ts +class SmartMigration { + public settings: ISmartMigrationOptions; + + constructor(options: ISmartMigrationOptions); + + /** Begin defining a step. Returns a chainable builder. */ + step(id: string): MigrationStepBuilder; + + /** + * The startup entry point. + * 1. Acquires the migration lock + * 2. Reads current ledger version (treats null as fresh install) + * 3. Validates the chain of registered steps + * 4. Computes the plan (which steps to run) + * 5. Executes them sequentially, checkpointing each + * 6. Releases the lock + * Returns a result describing what was applied/skipped. + */ + run(): Promise; + + /** Returns the plan without executing. Useful for `--dry-run` style probes. */ + plan(): Promise; + + /** Returns the current data version from the ledger, or null if uninitialised. */ + getCurrentVersion(): Promise; +} +``` + +### `IMigrationRunResult` + +```ts +export interface IMigrationRunResult { + currentVersionBefore: string | null; + currentVersionAfter: string; + targetVersion: string; + wasUpToDate: boolean; + wasFreshInstall: boolean; + stepsApplied: IMigrationStepResult[]; + stepsSkipped: IMigrationStepResult[]; // populated only on dry-run / when out of range + totalDurationMs: number; +} + +export interface IMigrationStepResult { + id: string; + fromVersion: string; + toVersion: string; + status: TMigrationStatus; // 'applied' | 'skipped' | 'failed' + durationMs: number; + startedAt: string; // ISO + finishedAt: string; // ISO + error?: { message: string; stack?: string }; +} +``` + +--- + +## Ledger model + +The ledger is the source of truth. There are two backends: + +### Mongo ledger (default when `db` is provided) + +Backed by an `EasyStore` (smartdata's existing `EasyStore`, see `/mnt/data/lossless/push.rocks/smartdata/ts/classes.easystore.ts:35-101`). The `nameId` is `smartmigration:`. Schema of the stored data: + +```ts +interface ISmartMigrationLedgerData { + currentVersion: string | null; + steps: Record; // keyed by step id + lock: { + holder: string | null; // random instance UUID + acquiredAt: string | null; // ISO + expiresAt: string | null; // ISO + }; + checkpoints: Record>; // stepId -> { key: value } +} +``` + +**Why EasyStore over a custom collection?** `EasyStore` already exists, is designed for exactly this kind of singleton-config-blob use case, handles its own collection setup lazily, and avoids polluting the user's DB with smartmigration-internal classes. The whole ledger fits in one document, which makes the lock CAS trivial. + +**Locking implementation.** Acquire by calling `easyStore.readAll()`, checking `lock.holder === null || lock.expiresAt < now`, then `easyStore.writeAll({ lock: { holder: instanceId, ... } })`. Re-read after writing to confirm we won the race (last-writer-wins is fine here because we re-check). Loop with backoff until `lockWaitMs` elapsed. This is admittedly not a true CAS — for v1 it's adequate; v2 can move to `findOneAndUpdate` against the underlying mongo collection if races become a problem. + +### S3 ledger (default when only `bucket` is provided) + +A single object at `/.smartmigration/.json` containing the same `ISmartMigrationLedgerData` shape. Reads use `bucket.fastGet`, writes use `bucket.fastPut` with `overwrite: true`. Locking is **best-effort** (S3 has no CAS without conditional writes); we set `lock.expiresAt` and re-read to detect races. **Documented limitation:** S3-only deployments should not run multiple SaaS instances against the same ledger simultaneously without external coordination — when both mongo and S3 are present (the common SaaS case), the mongo ledger is used and the lock works correctly. + +### Selection logic + +```ts +const backend = + options.ledgerBackend ?? + (options.db ? 'mongo' : options.bucket ? 's3' : null); +if (!backend) throw new SmartMigrationError('Either db or bucket must be provided'); +``` + +--- + +## Run algorithm + +``` +run(): + steps = registeredSteps // array, in registration order + validateStepChain(steps) // checks unique ids, no gaps in version chain + + acquireLock() + try: + ledger = readLedger() + currentVersion = ledger.currentVersion + + if currentVersion === null: + if isFreshInstall() and freshInstallVersion is set: + currentVersion = freshInstallVersion + writeLedger({ currentVersion }) + else: + currentVersion = steps[0].from // start from earliest + + if compareSemver(currentVersion, targetVersion) === 0: + return { wasUpToDate: true, ... } + + plan = computePlan(steps, currentVersion, targetVersion) + if plan.length === 0: + throw "no migration path from X to Y" + + for step in plan: + if dryRun: + skipped.push(step); continue + ctx = buildContext(step) + try: + await step.handler(ctx) + ledger.steps[step.id] = { ...result } + ledger.currentVersion = step.toVersion + writeLedger(ledger) + applied.push(step) + catch err: + ledger.steps[step.id] = { ...result, status: 'failed', error } + writeLedger(ledger) + throw err + + finally: + releaseLock() +``` + +### `isFreshInstall()` + +- Mongo: `db.mongoDb.listCollections({}, {nameOnly:true}).toArray()` → if every collection name starts with smartmigration's reserved prefix or matches the EasyStore class name, fresh. +- S3: open a `bucket.createCursor('')` and ask for one batch — if empty (after excluding `.smartmigration/` prefix), fresh. + +### `validateStepChain(steps)` + +- Each `step.id` must be unique +- Each `step.from` and `step.to` must be valid semver +- For consecutive steps `a, b`: `a.to === b.from` (strict equality, not semver-compare — forces explicit chains) +- `compareSemver(step.from, step.to) < 0` for every step + +### `computePlan(steps, current, target)` + +- Find the step where `from === current`. Take it and all subsequent steps until one has `to === target`. Return that slice. +- If `current` doesn't match any step's `from`, throw with a clear message naming the registered version chain. +- If we walk past `target` without matching, throw. + +--- + +## File layout + +Following the **flat-classes pattern** used by most push.rocks modules (smartproxy's nested layout is the exception, justified only by its size). The new module's `ts/` will look like: + +``` +ts/ +├── 00_commitinfo_data.ts // auto-generated by commitinfo on release +├── index.ts // re-exports the public surface +├── plugins.ts // central import barrel +├── interfaces.ts // I-prefixed public interfaces +├── types.ts // T-prefixed public type aliases +├── logger.ts // module-scoped Smartlog singleton +├── classes.smartmigration.ts // SmartMigration class + SmartMigrationError +├── classes.migrationstep.ts // MigrationStepBuilder + internal MigrationStep +├── classes.migrationcontext.ts // buildContext() factory + checkpoint impl +├── classes.versionresolver.ts // semver-based plan computation + validation +└── ledgers/ + ├── classes.ledger.ts // abstract Ledger base + ├── classes.mongoledger.ts // EasyStore-backed implementation + └── classes.s3ledger.ts // bucket.fastPut/fastGet-backed implementation +``` + +### `ts/plugins.ts` content + +```ts +// node native scope +import { randomUUID } from 'node:crypto'; +export { randomUUID }; + +// pushrocks scope +import * as smartdata from '@push.rocks/smartdata'; +import * as smartbucket from '@push.rocks/smartbucket'; +import * as smartlog from '@push.rocks/smartlog'; +import * as smartlogDestinationLocal from '@push.rocks/smartlog/destination-local'; +import * as smartversion from '@push.rocks/smartversion'; +import * as smarttime from '@push.rocks/smarttime'; +import * as smartpromise from '@push.rocks/smartpromise'; +export { + smartdata, smartbucket, smartlog, smartlogDestinationLocal, + smartversion, smarttime, smartpromise, +}; + +// third-party scope (driver re-exports for type access) +import type * as mongodb from 'mongodb'; +import type * as awsSdk from '@aws-sdk/client-s3'; +export type { mongodb, awsSdk }; +``` + +`smartdata` and `smartbucket` are **peerDependencies** (not direct dependencies) — users will already have one or both, and we don't want to duplicate them. Listed in `dependencies`: `@push.rocks/smartlog`, `@push.rocks/smartversion`, `@push.rocks/smarttime`, `@push.rocks/smartpromise`. Listed in `peerDependencies` (optional): `@push.rocks/smartdata`, `@push.rocks/smartbucket`. Listed in `devDependencies` for tests: both peers + `@push.rocks/smartmongo` (in-memory mongo). + +--- + +## Project scaffolding files + +These mirror the smartproxy conventions, with smartproxy-specific Rust bits removed. + +### `package.json` + +```json +{ + "name": "@push.rocks/smartmigration", + "version": "1.0.0", + "private": false, + "description": "Unified migration runner for MongoDB (smartdata) and S3 (smartbucket) — designed to be invoked at SaaS app startup, with semver-based version tracking, sequential step execution, idempotent re-runs, and per-step resumable checkpoints.", + "main": "dist_ts/index.js", + "typings": "dist_ts/index.d.ts", + "type": "module", + "author": "Lossless GmbH", + "license": "MIT", + "scripts": { + "test": "(tstest test/**/test*.ts --verbose --timeout 120 --logfile)", + "build": "(tsbuild tsfolders --allowimplicitany)", + "format": "(gitzone format)", + "buildDocs": "tsdoc" + }, + "devDependencies": { + "@git.zone/tsbuild": "^4.4.0", + "@git.zone/tsrun": "^2.0.2", + "@git.zone/tstest": "^3.6.0", + "@push.rocks/smartdata": "^7.1.6", + "@push.rocks/smartbucket": "^4.5.1", + "@push.rocks/smartmongo": "^7.0.0", + "@types/node": "^25.5.0", + "typescript": "^6.0.2" + }, + "dependencies": { + "@push.rocks/smartlog": "^3.2.1", + "@push.rocks/smartpromise": "^4.2.3", + "@push.rocks/smarttime": "^4.1.1", + "@push.rocks/smartversion": "^3.0.5" + }, + "peerDependencies": { + "@push.rocks/smartdata": "^7.1.6", + "@push.rocks/smartbucket": "^4.5.1" + }, + "peerDependenciesMeta": { + "@push.rocks/smartdata": { "optional": true }, + "@push.rocks/smartbucket": { "optional": true } + }, + "files": [ + "ts/**/*", + "dist/**/*", + "dist_*/**/*", + "dist_ts/**/*", + ".smartconfig.json", + "readme.md", + "changelog.md" + ], + "keywords": [ + "migration", "schema migration", "data migration", + "mongodb", "s3", "smartdata", "smartbucket", + "saas", "startup migration", "semver", "idempotent", + "ledger", "rolling deploy" + ], + "homepage": "https://code.foss.global/push.rocks/smartmigration#readme", + "repository": { + "type": "git", + "url": "https://code.foss.global/push.rocks/smartmigration.git" + }, + "bugs": { + "url": "https://code.foss.global/push.rocks/smartmigration/issues" + }, + "pnpm": { + "overrides": {}, + "onlyBuiltDependencies": ["mongodb-memory-server"] + } +} +``` + +### `tsconfig.json` (verbatim from smartproxy) + +```json +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "esModuleInterop": true, + "verbatimModuleSyntax": true + }, + "exclude": ["dist_*/**/*.d.ts"] +} +``` + +### `.smartconfig.json` — same shape as smartproxy's, with name/scope/repo updated and the `@git.zone/tsrust` block omitted. Description and keywords from package.json above. + +### `.gitignore` — verbatim from smartproxy minus the `rust/target` line. + +### `license` — MIT, copy from smartproxy. + +### `changelog.md` — single entry for `1.0.0 - - Initial release`. + +### `readme.hints.md` — empty stub. + +--- + +## Test plan + +Tests live in `test/` and follow the smartproxy/`tstest` conventions: every file ends with `export default tap.start();` and uses `expect`/`tap` from `@git.zone/tstest/tapbundle`. Use `@push.rocks/smartmongo` to spin up an in-memory mongo for tests; for S3 tests, mock against a small in-process fake (or skip and only test mongo paths in v1). + +Files to create: + +| File | What it covers | +|---|---| +| `test/test.basic.ts` | Constructor validates options; throws if neither db nor bucket given; default ledger backend selection | +| `test/test.builder.ts` | Step builder chains correctly, `.from().to().up()` registers a step, validation catches duplicate ids and gaps | +| `test/test.versionresolver.ts` | `computePlan` returns the right slice for various current/target combinations; throws on missing chain | +| `test/test.mongoledger.ts` | Read/write/lock against a real mongo via `smartmongo`; lock expiry; concurrent acquire retries | +| `test/test.run.mongo.ts` | End-to-end: define 3 steps, run from scratch, verify all applied; re-run is no-op; mid-step failure leaves ledger consistent | +| `test/test.run.checkpoint.ts` | Resumable step that crashes mid-way; second run resumes from checkpoint | +| `test/test.freshinstall.ts` | Empty db + `freshInstallVersion` set → jumps to that version, runs no steps | +| `test/test.dryrun.ts` | `dryRun: true` returns plan but does not write | + +Critical assertions for the end-to-end mongo test (`test/test.run.mongo.ts`): + +```ts +const db = await smartmongo.SmartMongo.createAndStart(); +const smartmig = new SmartMigration({ targetVersion: '2.0.0', db: db.smartdataDb }); +const log: string[] = []; +smartmig + .step('a').from('1.0.0').to('1.1.0').up(async () => { log.push('a'); }) + .step('b').from('1.1.0').to('1.5.0').up(async () => { log.push('b'); }) + .step('c').from('1.5.0').to('2.0.0').up(async () => { log.push('c'); }); + +const r1 = await smartmig.run(); +expect(r1.stepsApplied).toHaveLength(3); +expect(log).toEqual(['a', 'b', 'c']); +expect(r1.currentVersionAfter).toEqual('2.0.0'); + +const r2 = await smartmig.run(); +expect(r2.wasUpToDate).toBeTrue(); +expect(r2.stepsApplied).toHaveLength(0); +expect(log).toEqual(['a', 'b', 'c']); // unchanged +``` + +End-to-end verification path (manual smoke after implementation): write a tiny `.nogit/debug/saas-startup.ts` script that constructs a `SmartdataDb` against a local mongo, registers two no-op migrations, runs `smartmig.run()` twice, and prints the result both times — the second run must report `wasUpToDate: true`. + +--- + +## Critical files to create + +**Source (under `/mnt/data/lossless/push.rocks/smartmigration/`):** +- `package.json` +- `tsconfig.json` +- `.smartconfig.json` +- `.gitignore` +- `license` +- `changelog.md` +- `readme.md` (full structured README following the smartproxy section template — installation, what is it, quick start, core concepts, common use cases, API reference, troubleshooting, best practices, license) +- `readme.hints.md` (stub) +- `ts/00_commitinfo_data.ts` +- `ts/index.ts` +- `ts/plugins.ts` +- `ts/interfaces.ts` +- `ts/types.ts` +- `ts/logger.ts` +- `ts/classes.smartmigration.ts` +- `ts/classes.migrationstep.ts` +- `ts/classes.migrationcontext.ts` +- `ts/classes.versionresolver.ts` +- `ts/ledgers/classes.ledger.ts` +- `ts/ledgers/classes.mongoledger.ts` +- `ts/ledgers/classes.s3ledger.ts` +- `test/test.basic.ts` +- `test/test.builder.ts` +- `test/test.versionresolver.ts` +- `test/test.mongoledger.ts` +- `test/test.run.mongo.ts` +- `test/test.run.checkpoint.ts` +- `test/test.freshinstall.ts` +- `test/test.dryrun.ts` + +**Reused from existing modules (no need to create — these are already in dependencies):** +- `EasyStore` from smartdata (`/mnt/data/lossless/push.rocks/smartdata/ts/classes.easystore.ts:9-121`) — backs the mongo ledger +- `SmartdataDb.mongoDb` (raw `Db`) and `SmartdataDb.mongoDbClient` (raw `MongoClient`) for `ctx.mongo` and transactional sessions +- `SmartdataDb.startSession()` (`/mnt/data/lossless/push.rocks/smartdata/ts/classes.db.ts`) for `ctx.startSession()` +- `Bucket.fastGet` / `Bucket.fastPut` for the S3 ledger backend +- `Bucket.createCursor` (resumable token-based pagination, `/mnt/data/lossless/push.rocks/smartbucket/ts/classes.listcursor.ts`) — the canonical pattern for restartable S3 migrations, referenced in the readme example +- `SmartBucket.storageClient` for `ctx.s3` +- `Smartlog` from `@push.rocks/smartlog` for the module logger +- `compareVersions` from `@push.rocks/smartversion` for semver ordering diff --git a/test/helpers/services.ts b/test/helpers/services.ts new file mode 100644 index 0000000..9e9d426 --- /dev/null +++ b/test/helpers/services.ts @@ -0,0 +1,66 @@ +import { Qenv } from '@push.rocks/qenv'; +import * as smartdata from '@push.rocks/smartdata'; +import * as smartbucket from '@push.rocks/smartbucket'; + +const qenv = new Qenv(process.cwd(), process.cwd() + '/.nogit/'); + +/** + * Spin up a fresh `SmartdataDb` connected to the local mongo from .nogit/env.json, + * scoped to a unique database name so tests cannot collide. Returns the db plus + * a `cleanup` function that drops the database and closes the connection. + */ +export async function makeTestDb(suffix: string) { + const baseUrl = await qenv.getEnvVarOnDemandStrict('MONGODB_URL'); + const dbName = `smartmigration_test_${suffix}_${Date.now()}_${Math.floor(Math.random() * 1e6)}`; + // Replace the path component of the connection URL with our unique db name. + // Format from env.json: + // mongodb://defaultadmin:defaultpass@localhost:27970/push-rocks-smartmigration?authSource=admin + const url = new URL(baseUrl); + url.pathname = `/${dbName}`; + const db = new smartdata.SmartdataDb({ + mongoDbUrl: url.toString(), + mongoDbName: dbName, + }); + await db.init(); + + const cleanup = async () => { + try { + await db.mongoDb.dropDatabase(); + } catch { + /* ignore */ + } + try { + await db.close(); + } catch { + /* ignore */ + } + }; + + return { db, dbName, cleanup }; +} + +/** + * Connect to the local minio bucket from .nogit/env.json. The bucket is + * shared across tests, so each test should namespace its keys with a + * unique prefix and clean them up afterwards. + */ +export async function makeTestBucket() { + const sb = new smartbucket.SmartBucket({ + accessKey: await qenv.getEnvVarOnDemandStrict('S3_ACCESSKEY'), + accessSecret: await qenv.getEnvVarOnDemandStrict('S3_SECRETKEY'), + endpoint: await qenv.getEnvVarOnDemandStrict('S3_ENDPOINT'), + port: parseInt(await qenv.getEnvVarOnDemandStrict('S3_PORT'), 10), + useSsl: false, + }); + const bucketName = await qenv.getEnvVarOnDemandStrict('S3_BUCKET'); + + // The bucket may not exist yet — try to fetch it; if missing, create it. + let bucket: smartbucket.Bucket; + try { + bucket = await sb.getBucketByName(bucketName); + } catch { + bucket = (await sb.createBucket(bucketName)) as unknown as smartbucket.Bucket; + bucket = await sb.getBucketByName(bucketName); + } + return { sb, bucket, bucketName }; +} diff --git a/test/test.basic.ts b/test/test.basic.ts new file mode 100644 index 0000000..0cce149 --- /dev/null +++ b/test/test.basic.ts @@ -0,0 +1,93 @@ +import { tap, expect } from '@git.zone/tstest/tapbundle'; +import { SmartMigration, SmartMigrationError } from '../ts/index.js'; + +// Pure-logic tests for the SmartMigration constructor — no database required. + +tap.test('constructor: rejects empty options', async () => { + expect(() => new (SmartMigration as any)()).toThrow(); + expect(() => new (SmartMigration as any)(null)).toThrow(); +}); + +tap.test('constructor: requires targetVersion', async () => { + expect(() => new SmartMigration({} as any)).toThrow(); +}); + +tap.test('constructor: rejects invalid targetVersion', async () => { + let caught: SmartMigrationError | undefined; + try { + // not a real semver + new SmartMigration({ targetVersion: 'not-a-version', db: {} as any }); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught).toBeInstanceOf(SmartMigrationError); + expect(caught!.code).toEqual('INVALID_VERSION'); +}); + +tap.test('constructor: rejects when neither db nor bucket given', async () => { + let caught: SmartMigrationError | undefined; + try { + new SmartMigration({ targetVersion: '1.0.0' }); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught).toBeInstanceOf(SmartMigrationError); + expect(caught!.code).toEqual('NO_RESOURCES'); +}); + +tap.test('constructor: defaults ledgerBackend to "mongo" when db is given', async () => { + const m = new SmartMigration({ + targetVersion: '1.0.0', + db: {} as any, + }); + expect(m.settings.ledgerBackend).toEqual('mongo'); + expect(m.settings.ledgerName).toEqual('smartmigration'); + expect(m.settings.lockWaitMs).toEqual(60_000); + expect(m.settings.lockTtlMs).toEqual(600_000); + expect(m.settings.dryRun).toBeFalse(); +}); + +tap.test('constructor: defaults ledgerBackend to "s3" when only bucket is given', async () => { + const m = new SmartMigration({ + targetVersion: '1.0.0', + bucket: {} as any, + }); + expect(m.settings.ledgerBackend).toEqual('s3'); +}); + +tap.test('constructor: rejects mongo backend without db', async () => { + let caught: SmartMigrationError | undefined; + try { + new SmartMigration({ + targetVersion: '1.0.0', + bucket: {} as any, + ledgerBackend: 'mongo', + }); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught).toBeInstanceOf(SmartMigrationError); + expect(caught!.code).toEqual('LEDGER_BACKEND_MISMATCH'); +}); + +tap.test('constructor: rejects s3 backend without bucket', async () => { + let caught: SmartMigrationError | undefined; + try { + new SmartMigration({ + targetVersion: '1.0.0', + db: {} as any, + ledgerBackend: 's3', + }); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught).toBeInstanceOf(SmartMigrationError); + expect(caught!.code).toEqual('LEDGER_BACKEND_MISMATCH'); +}); + +tap.test('step(): rejects empty id', async () => { + const m = new SmartMigration({ targetVersion: '1.0.0', db: {} as any }); + expect(() => m.step('')).toThrow(); +}); + +export default tap.start(); diff --git a/test/test.builder.ts b/test/test.builder.ts new file mode 100644 index 0000000..2c89621 --- /dev/null +++ b/test/test.builder.ts @@ -0,0 +1,78 @@ +import { tap, expect } from '@git.zone/tstest/tapbundle'; +import { SmartMigration, SmartMigrationError } from '../ts/index.js'; + +// Tests for the MigrationStepBuilder fluent chain. + +tap.test('step builder: registers a single step', async () => { + const m = new SmartMigration({ targetVersion: '1.0.0', db: {} as any }); + m.step('a').from('1.0.0').to('1.1.0').up(async () => {}); + const steps = m.getRegisteredSteps(); + expect(steps).toHaveLength(1); + expect(steps[0].id).toEqual('a'); + expect(steps[0].fromVersion).toEqual('1.0.0'); + expect(steps[0].toVersion).toEqual('1.1.0'); + expect(steps[0].isResumable).toBeFalse(); + expect(steps[0].description).toBeUndefined(); +}); + +tap.test('step builder: chains multiple steps via the parent', async () => { + const m = new SmartMigration({ targetVersion: '2.0.0', db: {} as any }); + m + .step('a').from('1.0.0').to('1.1.0').up(async () => {}) + .step('b').from('1.1.0').to('1.5.0').up(async () => {}) + .step('c').from('1.5.0').to('2.0.0').up(async () => {}); + expect(m.getRegisteredSteps()).toHaveLength(3); + expect(m.getRegisteredSteps().map((s) => s.id)).toEqual(['a', 'b', 'c']); +}); + +tap.test('step builder: stores description and resumable', async () => { + const m = new SmartMigration({ targetVersion: '1.1.0', db: {} as any }); + m + .step('with-meta') + .from('1.0.0') + .to('1.1.0') + .description('does important things') + .resumable() + .up(async () => {}); + const step = m.getRegisteredSteps()[0]; + expect(step.description).toEqual('does important things'); + expect(step.isResumable).toBeTrue(); +}); + +tap.test('step builder: requires .from() before .up()', async () => { + const m = new SmartMigration({ targetVersion: '1.0.0', db: {} as any }); + let caught: SmartMigrationError | undefined; + try { + (m.step('bad').to('1.1.0') as any).up(async () => {}); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught).toBeInstanceOf(SmartMigrationError); + expect(caught!.code).toEqual('STEP_MISSING_FROM'); +}); + +tap.test('step builder: requires .to() before .up()', async () => { + const m = new SmartMigration({ targetVersion: '1.0.0', db: {} as any }); + let caught: SmartMigrationError | undefined; + try { + (m.step('bad').from('1.0.0') as any).up(async () => {}); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught).toBeInstanceOf(SmartMigrationError); + expect(caught!.code).toEqual('STEP_MISSING_TO'); +}); + +tap.test('step builder: rejects non-function handler', async () => { + const m = new SmartMigration({ targetVersion: '1.0.0', db: {} as any }); + let caught: SmartMigrationError | undefined; + try { + (m.step('bad').from('1.0.0').to('1.1.0') as any).up('not-a-function'); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught).toBeInstanceOf(SmartMigrationError); + expect(caught!.code).toEqual('STEP_HANDLER_NOT_FUNCTION'); +}); + +export default tap.start(); diff --git a/test/test.dryrun.ts b/test/test.dryrun.ts new file mode 100644 index 0000000..78a47d1 --- /dev/null +++ b/test/test.dryrun.ts @@ -0,0 +1,58 @@ +import { tap, expect } from '@git.zone/tstest/tapbundle'; +import { makeTestDb } from './helpers/services.js'; +import type * as smartdata from '@push.rocks/smartdata'; +import { SmartMigration } from '../ts/index.js'; + +let db: smartdata.SmartdataDb; +let cleanup: () => Promise; + +tap.test('setup: connect shared db', async () => { + const r = await makeTestDb('dryrun'); + db = r.db; + cleanup = r.cleanup; +}); + +tap.test('dryRun: returns plan without invoking handlers', async () => { + const m = new SmartMigration({ + targetVersion: '2.0.0', + db, + ledgerName: 'dryrun', + dryRun: true, + }); + let stepCalled = false; + m + .step('a').from('1.0.0').to('1.5.0').up(async () => { stepCalled = true; }) + .step('b').from('1.5.0').to('2.0.0').up(async () => { stepCalled = true; }); + + const r = await m.run(); + expect(stepCalled).toBeFalse(); + expect(r.stepsApplied).toHaveLength(0); + expect(r.stepsSkipped).toHaveLength(2); + expect(r.stepsSkipped.map((s) => s.id)).toEqual(['a', 'b']); + + // The ledger should still be in its initial state (currentVersion = null). + const current = await m.getCurrentVersion(); + expect(current).toBeNull(); +}); + +tap.test('plan(): returns plan without writing or running', async () => { + const m = new SmartMigration({ targetVersion: '2.0.0', db, ledgerName: 'plan_only' }); + let stepCalled = false; + m + .step('a').from('1.0.0').to('2.0.0').up(async () => { stepCalled = true; }); + + const planResult = await m.plan(); + expect(stepCalled).toBeFalse(); + expect(planResult.stepsSkipped).toHaveLength(1); + expect(planResult.stepsApplied).toHaveLength(0); + + // Plan does not modify the ledger. + const current = await m.getCurrentVersion(); + expect(current).toBeNull(); +}); + +tap.test('cleanup: close shared db', async () => { + await cleanup(); +}); + +export default tap.start(); diff --git a/test/test.freshinstall.ts b/test/test.freshinstall.ts new file mode 100644 index 0000000..2bf5fb0 --- /dev/null +++ b/test/test.freshinstall.ts @@ -0,0 +1,77 @@ +import { tap, expect } from '@git.zone/tstest/tapbundle'; +import { makeTestDb } from './helpers/services.js'; +import type * as smartdata from '@push.rocks/smartdata'; +import { SmartMigration } from '../ts/index.js'; + +// Shared db across the file. Each test uses a unique ledgerName for isolation. +// Note: the fresh-install detector checks for any non-reserved collection, so +// tests that explicitly create user data must clean it up after themselves +// (or other tests would no longer see "fresh"). For simplicity, the +// not-fresh test runs LAST and we don't bother cleaning up after it. +let db: smartdata.SmartdataDb; +let cleanup: () => Promise; + +tap.test('setup: connect shared db', async () => { + const r = await makeTestDb('freshinstall'); + db = r.db; + cleanup = r.cleanup; +}); + +tap.test('freshInstall: jumps to freshInstallVersion when DB is empty', async () => { + // Database is empty (only the SmartdataEasyStore collection may exist + // from previous tests' ledgers, which is whitelisted by isFreshInstall()). + const m = new SmartMigration({ + targetVersion: '5.0.0', + db, + ledgerName: 'jump', + freshInstallVersion: '5.0.0', + }); + let stepCalled = false; + m + .step('a').from('1.0.0').to('2.0.0').up(async () => { stepCalled = true; }) + .step('b').from('2.0.0').to('5.0.0').up(async () => { stepCalled = true; }); + + const r = await m.run(); + expect(stepCalled).toBeFalse(); + expect(r.currentVersionAfter).toEqual('5.0.0'); + expect(r.wasFreshInstall).toBeTrue(); + expect(r.stepsApplied).toHaveLength(0); +}); + +tap.test('freshInstall: without freshInstallVersion, starts from earliest step', async () => { + // Even with freshInstallVersion unset, the db is still empty of user + // collections, so the runner should start from the first step's `from` + // version and run all steps in order. + const m = new SmartMigration({ targetVersion: '2.0.0', db, ledgerName: 'no_freshversion' }); + const log: string[] = []; + m + .step('a').from('1.0.0').to('1.5.0').up(async () => { log.push('a'); }) + .step('b').from('1.5.0').to('2.0.0').up(async () => { log.push('b'); }); + const r = await m.run(); + expect(log).toEqual(['a', 'b']); + expect(r.currentVersionAfter).toEqual('2.0.0'); +}); + +tap.test('freshInstall: runs steps when DB has user collections (not fresh)', async () => { + // Pre-seed the DB with a user collection so isFreshInstall() returns false. + await db.mongoDb.collection('users_pre').insertOne({ name: 'preexisting' }); + + const m = new SmartMigration({ + targetVersion: '2.0.0', + db, + ledgerName: 'not_fresh', + freshInstallVersion: '2.0.0', + }); + let aCalled = false; + m.step('a').from('1.0.0').to('2.0.0').up(async () => { aCalled = true; }); + const r = await m.run(); + expect(aCalled).toBeTrue(); + expect(r.wasFreshInstall).toBeFalse(); + expect(r.currentVersionAfter).toEqual('2.0.0'); +}); + +tap.test('cleanup: close shared db', async () => { + await cleanup(); +}); + +export default tap.start(); diff --git a/test/test.mongoledger.ts b/test/test.mongoledger.ts new file mode 100644 index 0000000..884e599 --- /dev/null +++ b/test/test.mongoledger.ts @@ -0,0 +1,81 @@ +import { tap, expect } from '@git.zone/tstest/tapbundle'; +import { makeTestDb } from './helpers/services.js'; +import type * as smartdata from '@push.rocks/smartdata'; +import { MongoLedger } from '../ts/ledgers/classes.mongoledger.js'; + +// Smartdata's CollectionFactory caches collections by class name globally +// (see classes.collection.ts:22), so we MUST share a single db across all +// tests in a file. We isolate tests via unique ledger names — the EasyStore +// stores data keyed by `nameId`, so distinct ledger names live in the same +// underlying mongo collection without interference. + +let db: smartdata.SmartdataDb; +let cleanup: () => Promise; + +tap.test('setup: connect shared db', async () => { + const r = await makeTestDb('mongoledger'); + db = r.db; + cleanup = r.cleanup; +}); + +tap.test('MongoLedger: init creates an empty ledger', async () => { + const ledger = new MongoLedger(db, 'init-test'); + await ledger.init(); + const data = await ledger.read(); + expect(data.currentVersion).toBeNull(); + expect(data.steps).toEqual({}); + expect(data.lock.holder).toBeNull(); + expect(data.checkpoints).toEqual({}); +}); + +tap.test('MongoLedger: write+read roundtrips', async () => { + const ledger = new MongoLedger(db, 'rw-test'); + await ledger.init(); + await ledger.write({ + currentVersion: '1.5.0', + steps: { foo: { id: 'foo', fromVersion: '1.0.0', toVersion: '1.5.0', status: 'applied', startedAt: 'a', finishedAt: 'b', durationMs: 12 } }, + lock: { holder: null, acquiredAt: null, expiresAt: null }, + checkpoints: { foo: { progress: 42 } }, + }); + const round = await ledger.read(); + expect(round.currentVersion).toEqual('1.5.0'); + expect(round.steps['foo'].durationMs).toEqual(12); + expect((round.checkpoints['foo'] as any).progress).toEqual(42); +}); + +tap.test('MongoLedger: lock acquire/release', async () => { + const ledger = new MongoLedger(db, 'lock-test'); + await ledger.init(); + + const acquired = await ledger.acquireLock('holder-A', 60_000); + expect(acquired).toBeTrue(); + + // A second acquire from a different holder should fail. + const acquired2 = await ledger.acquireLock('holder-B', 60_000); + expect(acquired2).toBeFalse(); + + // Release lets holder-B in. + await ledger.releaseLock('holder-A'); + const acquired3 = await ledger.acquireLock('holder-B', 60_000); + expect(acquired3).toBeTrue(); +}); + +tap.test('MongoLedger: expired lock can be stolen', async () => { + const ledger = new MongoLedger(db, 'expire-test'); + await ledger.init(); + + // Acquire with a 1ms TTL so it's instantly expired. + const got = await ledger.acquireLock('stale-holder', 1); + expect(got).toBeTrue(); + await new Promise((r) => setTimeout(r, 10)); + + // Now another holder should be able to take over (lock is expired). + const got2 = await ledger.acquireLock('fresh-holder', 60_000); + expect(got2).toBeTrue(); +}); + +tap.test('cleanup: close shared db', async () => { + await cleanup(); +}); + +export default tap.start(); diff --git a/test/test.run.checkpoint.ts b/test/test.run.checkpoint.ts new file mode 100644 index 0000000..35882b9 --- /dev/null +++ b/test/test.run.checkpoint.ts @@ -0,0 +1,72 @@ +import { tap, expect } from '@git.zone/tstest/tapbundle'; +import { makeTestDb } from './helpers/services.js'; +import type * as smartdata from '@push.rocks/smartdata'; +import { SmartMigration, SmartMigrationError } from '../ts/index.js'; + +let db: smartdata.SmartdataDb; +let cleanup: () => Promise; + +tap.test('setup: connect shared db', async () => { + const r = await makeTestDb('checkpoint'); + db = r.db; + cleanup = r.cleanup; +}); + +tap.test('checkpoint: resumable step writes and re-reads progress across runs', async () => { + // First runner: simulate a crash after writing the first half of the work. + const m1 = new SmartMigration({ targetVersion: '1.1.0', db, ledgerName: 'resume' }); + let crashed = false; + m1.step('big-job').from('1.0.0').to('1.1.0').resumable().up(async (ctx) => { + const seen = (await ctx.checkpoint!.read('processed')) ?? 0; + // Pretend we processed items 0..4 and then crash. + for (let i = seen; i < 5; i++) { + await ctx.checkpoint!.write('processed', i + 1); + } + crashed = true; + throw new Error('simulated crash mid-step'); + }); + + let caught: SmartMigrationError | undefined; + try { + await m1.run(); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught).toBeInstanceOf(SmartMigrationError); + expect(crashed).toBeTrue(); + + // Second runner: should see the checkpoint and resume from item 5. + const m2 = new SmartMigration({ targetVersion: '1.1.0', db, ledgerName: 'resume' }); + let resumedFrom: number | undefined; + let finalCount: number | undefined; + m2.step('big-job').from('1.0.0').to('1.1.0').resumable().up(async (ctx) => { + resumedFrom = (await ctx.checkpoint!.read('processed')) ?? 0; + // Process items 5..9. + let n = resumedFrom; + while (n < 10) { + n++; + await ctx.checkpoint!.write('processed', n); + } + finalCount = n; + }); + const r = await m2.run(); + expect(resumedFrom).toEqual(5); + expect(finalCount).toEqual(10); + expect(r.currentVersionAfter).toEqual('1.1.0'); +}); + +tap.test('checkpoint: ctx.checkpoint is undefined for non-resumable steps', async () => { + const m = new SmartMigration({ targetVersion: '1.1.0', db, ledgerName: 'noresume' }); + let observed: boolean | undefined; + m.step('plain').from('1.0.0').to('1.1.0').up(async (ctx) => { + observed = ctx.checkpoint === undefined; + }); + await m.run(); + expect(observed).toBeTrue(); +}); + +tap.test('cleanup: close shared db', async () => { + await cleanup(); +}); + +export default tap.start(); diff --git a/test/test.run.mongo.ts b/test/test.run.mongo.ts new file mode 100644 index 0000000..1262034 --- /dev/null +++ b/test/test.run.mongo.ts @@ -0,0 +1,124 @@ +import { tap, expect } from '@git.zone/tstest/tapbundle'; +import { makeTestDb } from './helpers/services.js'; +import type * as smartdata from '@push.rocks/smartdata'; +import { SmartMigration, SmartMigrationError } from '../ts/index.js'; + +// Shared db across the file (see test.mongoledger.ts for the rationale). +// Each test uses a unique ledgerName for isolation. +let db: smartdata.SmartdataDb; +let cleanup: () => Promise; + +tap.test('setup: connect shared db', async () => { + const r = await makeTestDb('run_mongo'); + db = r.db; + cleanup = r.cleanup; +}); + +tap.test('run: applies all steps from scratch', async () => { + const m = new SmartMigration({ targetVersion: '2.0.0', db, ledgerName: 'scratch' }); + const log: string[] = []; + m + .step('a').from('1.0.0').to('1.1.0').up(async () => { log.push('a'); }) + .step('b').from('1.1.0').to('1.5.0').up(async () => { log.push('b'); }) + .step('c').from('1.5.0').to('2.0.0').up(async () => { log.push('c'); }); + + const r = await m.run(); + expect(r.stepsApplied).toHaveLength(3); + expect(log).toEqual(['a', 'b', 'c']); + expect(r.currentVersionAfter).toEqual('2.0.0'); + expect(r.wasUpToDate).toBeFalse(); + expect(r.targetVersion).toEqual('2.0.0'); +}); + +tap.test('run: second run is a no-op', async () => { + const m = new SmartMigration({ targetVersion: '2.0.0', db, ledgerName: 'idempotent' }); + const log: string[] = []; + m + .step('a').from('1.0.0').to('1.1.0').up(async () => { log.push('a'); }) + .step('b').from('1.1.0').to('2.0.0').up(async () => { log.push('b'); }); + + const r1 = await m.run(); + expect(r1.stepsApplied).toHaveLength(2); + expect(log).toEqual(['a', 'b']); + + // Re-run with a freshly-constructed runner using the same ledger. + const m2 = new SmartMigration({ targetVersion: '2.0.0', db, ledgerName: 'idempotent' }); + m2 + .step('a').from('1.0.0').to('1.1.0').up(async () => { log.push('a-again'); }) + .step('b').from('1.1.0').to('2.0.0').up(async () => { log.push('b-again'); }); + const r2 = await m2.run(); + expect(r2.wasUpToDate).toBeTrue(); + expect(r2.stepsApplied).toHaveLength(0); + expect(log).toEqual(['a', 'b']); // no new entries +}); + +tap.test('run: failing step throws and persists failure', async () => { + const m = new SmartMigration({ targetVersion: '2.0.0', db, ledgerName: 'failure' }); + let aCalled = false; + m + .step('a').from('1.0.0').to('1.1.0').up(async () => { aCalled = true; }) + .step('b').from('1.1.0').to('2.0.0').up(async () => { throw new Error('boom'); }); + + let caught: SmartMigrationError | undefined; + try { + await m.run(); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught).toBeInstanceOf(SmartMigrationError); + expect(caught!.code).toEqual('STEP_FAILED'); + expect(aCalled).toBeTrue(); + + // Ledger should be at 1.1.0 (after step a, before failed step b). + const current = await m.getCurrentVersion(); + expect(current).toEqual('1.1.0'); +}); + +tap.test('run: ctx exposes db, mongo, and step metadata', async () => { + const m = new SmartMigration({ targetVersion: '1.1.0', db, ledgerName: 'ctx' }); + let observed: { hasDb: boolean; hasMongo: boolean; stepId: string; from: string; to: string } | null = null; + m.step('check-ctx').from('1.0.0').to('1.1.0').up(async (ctx) => { + observed = { + hasDb: !!ctx.db, + hasMongo: !!ctx.mongo, + stepId: ctx.step.id, + from: ctx.step.fromVersion, + to: ctx.step.toVersion, + }; + // exercise raw mongo + await ctx.mongo!.collection('users_ctx_test').insertOne({ name: 'alice' }); + }); + await m.run(); + expect(observed).not.toBeNull(); + expect(observed!.hasDb).toBeTrue(); + expect(observed!.hasMongo).toBeTrue(); + expect(observed!.stepId).toEqual('check-ctx'); + expect(observed!.from).toEqual('1.0.0'); + expect(observed!.to).toEqual('1.1.0'); + // verify the data the step wrote + const found = await db.mongoDb.collection('users_ctx_test').findOne({ name: 'alice' }); + expect(found).not.toBeNull(); +}); + +tap.test('run: ctx.startSession works inside a step', async () => { + const m = new SmartMigration({ targetVersion: '1.1.0', db, ledgerName: 'session' }); + let sessionWasUsed = false; + m.step('with-session').from('1.0.0').to('1.1.0').up(async (ctx) => { + const session = ctx.startSession(); + try { + sessionWasUsed = !!session.id; + await session.endSession(); + } catch (err) { + await session.endSession(); + throw err; + } + }); + await m.run(); + expect(sessionWasUsed).toBeTrue(); +}); + +tap.test('cleanup: close shared db', async () => { + await cleanup(); +}); + +export default tap.start(); diff --git a/test/test.run.s3.ts b/test/test.run.s3.ts new file mode 100644 index 0000000..83791a7 --- /dev/null +++ b/test/test.run.s3.ts @@ -0,0 +1,103 @@ +import { tap, expect } from '@git.zone/tstest/tapbundle'; +import { makeTestBucket } from './helpers/services.js'; +import type * as smartbucket from '@push.rocks/smartbucket'; +import { SmartMigration } from '../ts/index.js'; + +// End-to-end test of an S3-backed migration. Each test uses a unique +// `ledgerName` so its `.smartmigration/.json` sidecar object does +// not collide with other tests in the file. + +let bucket: smartbucket.Bucket; + +tap.test('setup: connect to bucket', async () => { + const r = await makeTestBucket(); + bucket = r.bucket; + // Wipe the smartmigration sidecar prefix from any prior runs. + for await (const key of bucket.listAllObjects('.smartmigration/')) { + await bucket.fastRemove({ path: key }); + } +}); + +tap.test('s3 run: applies an S3 migration step from scratch', async () => { + const m = new SmartMigration({ + targetVersion: '2.0.0', + bucket, + ledgerName: 'reorganize', + }); + + // Pre-seed three "uploads/" objects so the migration has work to do. + await bucket.fastPut({ path: 'uploads/a.txt', contents: 'a' }); + await bucket.fastPut({ path: 'uploads/b.txt', contents: 'b' }); + await bucket.fastPut({ path: 'uploads/c.txt', contents: 'c' }); + + m.step('move-uploads').from('1.0.0').to('2.0.0').up(async (ctx) => { + for await (const key of ctx.bucket!.listAllObjects('uploads/')) { + const newPath = 'media/' + key.slice('uploads/'.length); + await ctx.bucket!.fastMove({ + sourcePath: key, + destinationPath: newPath, + overwrite: true, + }); + } + }); + + const r = await m.run(); + expect(r.stepsApplied).toHaveLength(1); + expect(r.currentVersionAfter).toEqual('2.0.0'); + + // Verify the data moved. + expect(await bucket.fastExists({ path: 'media/a.txt' })).toBeTrue(); + expect(await bucket.fastExists({ path: 'media/b.txt' })).toBeTrue(); + expect(await bucket.fastExists({ path: 'media/c.txt' })).toBeTrue(); + expect(await bucket.fastExists({ path: 'uploads/a.txt' })).toBeFalse(); + + // Cleanup so the next test starts clean. + for (const k of ['media/a.txt', 'media/b.txt', 'media/c.txt']) { + await bucket.fastRemove({ path: k }); + } +}); + +tap.test('s3 run: second run is a no-op', async () => { + const m = new SmartMigration({ + targetVersion: '1.1.0', + bucket, + ledgerName: 'noop', + }); + let calls = 0; + m.step('once').from('1.0.0').to('1.1.0').up(async () => { calls++; }); + + const r1 = await m.run(); + expect(r1.stepsApplied).toHaveLength(1); + expect(calls).toEqual(1); + + // Re-run with a fresh runner. + const m2 = new SmartMigration({ targetVersion: '1.1.0', bucket, ledgerName: 'noop' }); + m2.step('once').from('1.0.0').to('1.1.0').up(async () => { calls++; }); + const r2 = await m2.run(); + expect(r2.wasUpToDate).toBeTrue(); + expect(calls).toEqual(1); +}); + +tap.test('s3 ctx exposes bucket and s3 client', async () => { + const m = new SmartMigration({ + targetVersion: '1.1.0', + bucket, + ledgerName: 'ctx', + }); + let observed: { hasBucket: boolean; hasS3: boolean } | null = null; + m.step('check-ctx').from('1.0.0').to('1.1.0').up(async (ctx) => { + observed = { hasBucket: !!ctx.bucket, hasS3: !!ctx.s3 }; + }); + await m.run(); + expect(observed).not.toBeNull(); + expect(observed!.hasBucket).toBeTrue(); + expect(observed!.hasS3).toBeTrue(); +}); + +tap.test('cleanup: wipe smartmigration sidecars', async () => { + for await (const key of bucket.listAllObjects('.smartmigration/')) { + await bucket.fastRemove({ path: key }); + } +}); + +export default tap.start(); diff --git a/test/test.versionresolver.ts b/test/test.versionresolver.ts new file mode 100644 index 0000000..6a9112a --- /dev/null +++ b/test/test.versionresolver.ts @@ -0,0 +1,151 @@ +import { tap, expect } from '@git.zone/tstest/tapbundle'; +import { VersionResolver, SmartMigrationError } from '../ts/index.js'; +import type { IMigrationStepDefinition } from '../ts/index.js'; + +const noopHandler = async () => {}; + +function makeStep(id: string, from: string, to: string): IMigrationStepDefinition { + return { id, fromVersion: from, toVersion: to, isResumable: false, handler: noopHandler }; +} + +tap.test('equals / lessThan / greaterThan', async () => { + expect(VersionResolver.equals('1.0.0', '1.0.0')).toBeTrue(); + expect(VersionResolver.equals('1.0.0', '1.0.1')).toBeFalse(); + expect(VersionResolver.lessThan('1.0.0', '1.0.1')).toBeTrue(); + expect(VersionResolver.greaterThan('2.0.0', '1.99.99')).toBeTrue(); +}); + +tap.test('assertValid: throws on garbage', async () => { + let caught: SmartMigrationError | undefined; + try { + VersionResolver.assertValid('not-a-version', 'test'); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught).toBeInstanceOf(SmartMigrationError); + expect(caught!.code).toEqual('INVALID_VERSION'); +}); + +tap.test('validateChain: empty chain is valid', async () => { + VersionResolver.validateChain([]); +}); + +tap.test('validateChain: catches duplicate ids', async () => { + let caught: SmartMigrationError | undefined; + try { + VersionResolver.validateChain([ + makeStep('a', '1.0.0', '1.1.0'), + makeStep('a', '1.1.0', '1.2.0'), + ]); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught!.code).toEqual('DUPLICATE_STEP_ID'); +}); + +tap.test('validateChain: catches non-increasing step', async () => { + let caught: SmartMigrationError | undefined; + try { + VersionResolver.validateChain([makeStep('a', '1.5.0', '1.5.0')]); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught!.code).toEqual('NON_INCREASING_STEP'); +}); + +tap.test('validateChain: catches gap in chain', async () => { + let caught: SmartMigrationError | undefined; + try { + VersionResolver.validateChain([ + makeStep('a', '1.0.0', '1.1.0'), + makeStep('b', '1.2.0', '1.3.0'), // gap! a.to=1.1.0, b.from=1.2.0 + ]); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught!.code).toEqual('CHAIN_GAP'); +}); + +tap.test('validateChain: contiguous chain passes', async () => { + VersionResolver.validateChain([ + makeStep('a', '1.0.0', '1.1.0'), + makeStep('b', '1.1.0', '1.5.0'), + makeStep('c', '1.5.0', '2.0.0'), + ]); +}); + +tap.test('computePlan: returns empty when current === target', async () => { + const steps = [makeStep('a', '1.0.0', '1.1.0')]; + expect(VersionResolver.computePlan(steps, '1.0.0', '1.0.0')).toEqual([]); +}); + +tap.test('computePlan: returns full chain when starting from beginning', async () => { + const steps = [ + makeStep('a', '1.0.0', '1.1.0'), + makeStep('b', '1.1.0', '1.5.0'), + makeStep('c', '1.5.0', '2.0.0'), + ]; + const plan = VersionResolver.computePlan(steps, '1.0.0', '2.0.0'); + expect(plan.map((s) => s.id)).toEqual(['a', 'b', 'c']); +}); + +tap.test('computePlan: returns partial chain when starting in the middle', async () => { + const steps = [ + makeStep('a', '1.0.0', '1.1.0'), + makeStep('b', '1.1.0', '1.5.0'), + makeStep('c', '1.5.0', '2.0.0'), + ]; + const plan = VersionResolver.computePlan(steps, '1.1.0', '2.0.0'); + expect(plan.map((s) => s.id)).toEqual(['b', 'c']); +}); + +tap.test('computePlan: returns sub-slice when target is mid-chain', async () => { + const steps = [ + makeStep('a', '1.0.0', '1.1.0'), + makeStep('b', '1.1.0', '1.5.0'), + makeStep('c', '1.5.0', '2.0.0'), + ]; + const plan = VersionResolver.computePlan(steps, '1.0.0', '1.5.0'); + expect(plan.map((s) => s.id)).toEqual(['a', 'b']); +}); + +tap.test('computePlan: throws when current does not match any step from', async () => { + const steps = [ + makeStep('a', '1.0.0', '1.1.0'), + makeStep('b', '1.1.0', '2.0.0'), + ]; + let caught: SmartMigrationError | undefined; + try { + VersionResolver.computePlan(steps, '1.0.5', '2.0.0'); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught!.code).toEqual('CHAIN_NOT_AT_CURRENT'); +}); + +tap.test('computePlan: throws when target overshoots', async () => { + const steps = [ + makeStep('a', '1.0.0', '1.1.0'), + makeStep('b', '1.1.0', '2.0.0'), + ]; + let caught: SmartMigrationError | undefined; + try { + VersionResolver.computePlan(steps, '1.0.0', '1.5.0'); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught!.code).toEqual('TARGET_NOT_REACHABLE'); +}); + +tap.test('computePlan: rejects downgrade', async () => { + const steps = [makeStep('a', '1.0.0', '2.0.0')]; + let caught: SmartMigrationError | undefined; + try { + VersionResolver.computePlan(steps, '2.0.0', '1.0.0'); + } catch (err) { + caught = err as SmartMigrationError; + } + expect(caught!.code).toEqual('DOWNGRADE_NOT_SUPPORTED'); +}); + +export default tap.start(); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts new file mode 100644 index 0000000..bdc7c82 --- /dev/null +++ b/ts/00_commitinfo_data.ts @@ -0,0 +1,8 @@ +/** + * autocreated commitinfo by @push.rocks/commitinfo + */ +export const commitinfo = { + name: '@push.rocks/smartmigration', + version: '1.1.0', + description: 'Unified migration runner for MongoDB (smartdata) and S3 (smartbucket) — designed to be invoked at SaaS app startup, with semver-based version tracking, sequential step execution, idempotent re-runs, and per-step resumable checkpoints.' +} diff --git a/ts/classes.migrationcontext.ts b/ts/classes.migrationcontext.ts new file mode 100644 index 0000000..391240b --- /dev/null +++ b/ts/classes.migrationcontext.ts @@ -0,0 +1,109 @@ +import * as plugins from './plugins.js'; +import type { + IMigrationCheckpoint, + IMigrationContext, + IMigrationStepDefinition, + ISmartMigrationLedgerData, + ISmartMigrationOptions, +} from './interfaces.js'; +import type { Ledger } from './ledgers/classes.ledger.js'; +import { SmartMigrationError } from './classes.versionresolver.js'; + +/** + * Per-step parameters needed to build a context. Kept separate from + * `IMigrationContext` so the factory can stay framework-internal. + */ +export interface IBuildContextParams { + step: IMigrationStepDefinition; + options: ISmartMigrationOptions; + ledger: Ledger; + isDryRun: boolean; + log: plugins.smartlog.Smartlog; +} + +/** + * A `IMigrationCheckpoint` implementation that round-trips through the ledger. + * Each read fetches the latest ledger state; each write performs a + * read-modify-write of the `checkpoints[stepId]` sub-object. + */ +class LedgerCheckpoint implements IMigrationCheckpoint { + private ledger: Ledger; + private stepId: string; + + constructor(ledger: Ledger, stepId: string) { + this.ledger = ledger; + this.stepId = stepId; + } + + public async read(key: string): Promise { + const data = await this.ledger.read(); + const bag = data.checkpoints[this.stepId]; + if (!bag) return undefined; + return bag[key] as T | undefined; + } + + public async write(key: string, value: T): Promise { + const data = await this.ledger.read(); + const bag = data.checkpoints[this.stepId] ?? {}; + bag[key] = value as unknown; + data.checkpoints[this.stepId] = bag; + await this.ledger.write(data); + } + + public async clear(): Promise { + const data = await this.ledger.read(); + delete data.checkpoints[this.stepId]; + await this.ledger.write(data); + } +} + +/** + * Build the `IMigrationContext` passed to a step's `up` handler. + */ +export function buildContext(params: IBuildContextParams): IMigrationContext { + const { step, options, ledger, isDryRun, log } = params; + + const ctx: IMigrationContext = { + db: options.db, + bucket: options.bucket, + mongo: options.db?.mongoDb, + s3: extractS3Client(options.bucket), + step: { + id: step.id, + fromVersion: step.fromVersion, + toVersion: step.toVersion, + description: step.description, + isResumable: step.isResumable, + }, + log, + isDryRun, + checkpoint: step.isResumable ? new LedgerCheckpoint(ledger, step.id) : undefined, + startSession: () => { + if (!options.db) { + throw new SmartMigrationError( + 'NO_DB_CONFIGURED', + `Step "${step.id}" called ctx.startSession(), but no SmartdataDb was passed to SmartMigration.`, + { stepId: step.id }, + ); + } + return options.db.startSession(); + }, + }; + + return ctx; +} + +/** + * Extract the underlying AWS SDK v3 S3Client from a smartbucket Bucket. + * Uses `bucket.getStorageClient()` (added in @push.rocks/smartbucket 4.6.0) + * which is the typed, documented escape hatch for advanced S3 operations. + */ +function extractS3Client( + bucket: plugins.smartbucket.Bucket | undefined, +): plugins.TRawS3Client | undefined { + if (!bucket) return undefined; + // `getStorageClient` is typed as the actual S3Client, but it lives behind + // an optional peer dep type so we cast through unknown to keep this file + // compiling when smartbucket isn't installed by the consumer. + return (bucket as any).getStorageClient() as plugins.TRawS3Client | undefined; +} diff --git a/ts/classes.migrationstep.ts b/ts/classes.migrationstep.ts new file mode 100644 index 0000000..cd754fb --- /dev/null +++ b/ts/classes.migrationstep.ts @@ -0,0 +1,95 @@ +import type { + IMigrationContext, + IMigrationStepDefinition, +} from './interfaces.js'; +import type { SmartMigration } from './classes.smartmigration.js'; +import { SmartMigrationError } from './classes.versionresolver.js'; + +/** + * Builder returned by `SmartMigration.step(id)`. The chain is: + * .from('1.0.0').to('1.1.0').description('...').resumable().up(async ctx => {...}) + * + * `.up()` is the terminal call: it commits the step to its parent SmartMigration + * and returns that parent so further `.step(...)` calls can chain naturally. + */ +export class MigrationStepBuilder { + private parent: SmartMigration; + private id: string; + private _from: string | null = null; + private _to: string | null = null; + private _description: string | undefined; + private _resumable = false; + + constructor(parent: SmartMigration, id: string) { + this.parent = parent; + this.id = id; + } + + /** REQUIRED: the data version this step starts from. */ + public from(version: string): this { + this._from = version; + return this; + } + + /** REQUIRED: the data version this step ends at. */ + public to(version: string): this { + this._to = version; + return this; + } + + /** Optional human-readable description. */ + public description(text: string): this { + this._description = text; + return this; + } + + /** + * Mark the step as resumable. When set, the step's `up` handler receives a + * `ctx.checkpoint` object that persists arbitrary key/value state to the + * ledger between runs. + */ + public resumable(): this { + this._resumable = true; + return this; + } + + /** + * Terminal: register the step on the parent SmartMigration and return the + * parent so that further steps can be chained. + */ + public up(handler: (ctx: IMigrationContext) => Promise): SmartMigration { + if (this._from === null) { + throw new SmartMigrationError( + 'STEP_MISSING_FROM', + `Migration step "${this.id}" is missing .from(version) before .up().`, + { stepId: this.id }, + ); + } + if (this._to === null) { + throw new SmartMigrationError( + 'STEP_MISSING_TO', + `Migration step "${this.id}" is missing .to(version) before .up().`, + { stepId: this.id }, + ); + } + if (typeof handler !== 'function') { + throw new SmartMigrationError( + 'STEP_HANDLER_NOT_FUNCTION', + `Migration step "${this.id}" was passed a non-function to .up().`, + { stepId: this.id }, + ); + } + + const definition: IMigrationStepDefinition = { + id: this.id, + fromVersion: this._from, + toVersion: this._to, + description: this._description, + isResumable: this._resumable, + handler, + }; + + this.parent.registerStep(definition); + return this.parent; + } +} diff --git a/ts/classes.smartmigration.ts b/ts/classes.smartmigration.ts new file mode 100644 index 0000000..93ff5fb --- /dev/null +++ b/ts/classes.smartmigration.ts @@ -0,0 +1,442 @@ +import * as plugins from './plugins.js'; +import { logger as defaultLogger } from './logger.js'; +import { MigrationStepBuilder } from './classes.migrationstep.js'; +import { buildContext } from './classes.migrationcontext.js'; +import { SmartMigrationError, VersionResolver } from './classes.versionresolver.js'; +import { Ledger } from './ledgers/classes.ledger.js'; +import { MongoLedger } from './ledgers/classes.mongoledger.js'; +import { S3Ledger } from './ledgers/classes.s3ledger.js'; +import type { + IMigrationLedgerEntry, + IMigrationRunResult, + IMigrationStepDefinition, + IMigrationStepResult, + ISmartMigrationLedgerData, + ISmartMigrationOptions, +} from './interfaces.js'; +import type { TLedgerBackend } from './types.js'; + +export { SmartMigrationError }; + +const DEFAULT_LEDGER_NAME = 'smartmigration'; +const DEFAULT_LOCK_WAIT_MS = 60_000; +const DEFAULT_LOCK_TTL_MS = 600_000; +const LOCK_POLL_INTERVAL_MS = 500; + +/** + * SmartMigration — the runner. See readme.md for the full API. + * + * Lifecycle: + * 1. `new SmartMigration({...})` — creates the runner with the target version. + * 2. `.step('id').from(...).to(...).up(async ctx => { ... })` — register steps + * in the desired execution order. + * 3. `await migration.run()` — invoked at SaaS app startup; idempotent and + * fast on the happy path. + */ +export class SmartMigration { + public readonly settings: Required< + Omit + > & Pick; + + private steps: IMigrationStepDefinition[] = []; + private ledger: Ledger | null = null; + private instanceId: string; + private log: plugins.smartlog.Smartlog; + + constructor(options: ISmartMigrationOptions) { + if (!options || typeof options !== 'object') { + throw new SmartMigrationError('INVALID_OPTIONS', 'SmartMigration requires an options object.'); + } + if (!options.targetVersion) { + throw new SmartMigrationError( + 'MISSING_TARGET_VERSION', + 'SmartMigration requires `targetVersion` in its options.', + ); + } + VersionResolver.assertValid(options.targetVersion, 'options.targetVersion'); + + if (!options.db && !options.bucket) { + throw new SmartMigrationError( + 'NO_RESOURCES', + 'SmartMigration requires at least one of `db` (SmartdataDb) or `bucket` (smartbucket Bucket).', + ); + } + + const ledgerBackend: TLedgerBackend = + options.ledgerBackend ?? (options.db ? 'mongo' : 's3'); + + if (ledgerBackend === 'mongo' && !options.db) { + throw new SmartMigrationError( + 'LEDGER_BACKEND_MISMATCH', + 'ledgerBackend "mongo" requires `db` to be set.', + ); + } + if (ledgerBackend === 's3' && !options.bucket) { + throw new SmartMigrationError( + 'LEDGER_BACKEND_MISMATCH', + 'ledgerBackend "s3" requires `bucket` to be set.', + ); + } + + this.settings = { + targetVersion: options.targetVersion, + db: options.db, + bucket: options.bucket, + ledgerName: options.ledgerName ?? DEFAULT_LEDGER_NAME, + ledgerBackend, + freshInstallVersion: options.freshInstallVersion, + lockWaitMs: options.lockWaitMs ?? DEFAULT_LOCK_WAIT_MS, + lockTtlMs: options.lockTtlMs ?? DEFAULT_LOCK_TTL_MS, + dryRun: options.dryRun ?? false, + logger: options.logger, + }; + + this.log = options.logger ?? defaultLogger; + this.instanceId = plugins.randomUUID(); + } + + // ─── public API ──────────────────────────────────────────────────────────── + + /** Begin defining a step. Returns a chainable builder. */ + public step(id: string): MigrationStepBuilder { + if (!id || typeof id !== 'string') { + throw new SmartMigrationError('INVALID_STEP_ID', 'step(id) requires a non-empty string id.'); + } + return new MigrationStepBuilder(this, id); + } + + /** + * Register a step. Called by `MigrationStepBuilder.up()`. End users do not + * normally call this directly. + */ + public registerStep(definition: IMigrationStepDefinition): void { + this.steps.push(definition); + } + + /** All registered steps in registration order. Mostly useful for tests. */ + public getRegisteredSteps(): ReadonlyArray { + return this.steps; + } + + /** Returns the current data version from the ledger, or null if uninitialized. */ + public async getCurrentVersion(): Promise { + const ledger = await this.ensureLedger(); + const data = await ledger.read(); + return data.currentVersion; + } + + /** Returns the plan that would be executed without actually running it. */ + public async plan(): Promise { + return this.runInternal({ planOnly: true }); + } + + /** The startup entry point. Idempotent. Fast no-op if already at target. */ + public async run(): Promise { + return this.runInternal({ planOnly: false }); + } + + // ─── internals ───────────────────────────────────────────────────────────── + + private async runInternal(opts: { planOnly: boolean }): Promise { + VersionResolver.validateChain(this.steps); + + const ledger = await this.ensureLedger(); + + // Fast path: read once, return immediately if already at target. + const earlyData = await ledger.read(); + if ( + earlyData.currentVersion !== null && + VersionResolver.equals(earlyData.currentVersion, this.settings.targetVersion) + ) { + return { + currentVersionBefore: earlyData.currentVersion, + currentVersionAfter: earlyData.currentVersion, + targetVersion: this.settings.targetVersion, + wasUpToDate: true, + wasFreshInstall: false, + stepsApplied: [], + stepsSkipped: [], + totalDurationMs: 0, + }; + } + + // For dry runs, skip the lock entirely — we don't write anything. + if (opts.planOnly || this.settings.dryRun) { + return this.computeResultWithoutRun(earlyData); + } + + const lockHeld = await this.acquireLockWithBackoff(); + if (!lockHeld) { + throw new SmartMigrationError( + 'LOCK_TIMEOUT', + `Could not acquire migration lock within ${this.settings.lockWaitMs}ms. Another instance may be running migrations.`, + { lockWaitMs: this.settings.lockWaitMs }, + ); + } + + const runStart = Date.now(); + const applied: IMigrationStepResult[] = []; + let wasFreshInstall = false; + let currentVersionBefore: string | null = null; + + try { + // Re-read after acquiring lock (state may have changed while we waited). + let data = await ledger.read(); + currentVersionBefore = data.currentVersion; + + // Resolve initial version. + let currentVersion: string; + if (data.currentVersion === null) { + const fresh = await this.detectFreshInstall(); + if (fresh && this.settings.freshInstallVersion) { + wasFreshInstall = true; + currentVersion = this.settings.freshInstallVersion; + VersionResolver.assertValid(currentVersion, 'freshInstallVersion'); + data.currentVersion = currentVersion; + await ledger.write(data); + this.log.log('info', `smartmigration: fresh install detected, jumping to ${currentVersion}`); + } else { + if (this.steps.length === 0) { + // No steps and no current version — nothing to do. + data.currentVersion = this.settings.targetVersion; + await ledger.write(data); + return { + currentVersionBefore: null, + currentVersionAfter: this.settings.targetVersion, + targetVersion: this.settings.targetVersion, + wasUpToDate: false, + wasFreshInstall: true, + stepsApplied: [], + stepsSkipped: [], + totalDurationMs: Date.now() - runStart, + }; + } + currentVersion = this.steps[0].fromVersion; + data.currentVersion = currentVersion; + await ledger.write(data); + } + } else { + currentVersion = data.currentVersion; + } + + // Already at target after fresh-install resolution? + if (VersionResolver.equals(currentVersion, this.settings.targetVersion)) { + return { + currentVersionBefore, + currentVersionAfter: currentVersion, + targetVersion: this.settings.targetVersion, + wasUpToDate: true, + wasFreshInstall, + stepsApplied: [], + stepsSkipped: [], + totalDurationMs: Date.now() - runStart, + }; + } + + const plan = VersionResolver.computePlan( + this.steps, + currentVersion, + this.settings.targetVersion, + ); + + for (const step of plan) { + const startedAt = new Date(); + const stepStart = Date.now(); + let entry: IMigrationLedgerEntry; + try { + this.log.log( + 'info', + `smartmigration: running step "${step.id}" (${step.fromVersion} → ${step.toVersion})`, + ); + const ctx = buildContext({ + step, + options: { ...this.settings, db: this.settings.db, bucket: this.settings.bucket }, + ledger, + isDryRun: false, + log: this.log, + }); + await step.handler(ctx); + + const finishedAt = new Date(); + const durationMs = Date.now() - stepStart; + entry = { + id: step.id, + fromVersion: step.fromVersion, + toVersion: step.toVersion, + status: 'applied', + startedAt: startedAt.toISOString(), + finishedAt: finishedAt.toISOString(), + durationMs, + }; + // Re-read ledger to pick up any checkpoint writes the step made. + data = await ledger.read(); + data.steps[step.id] = entry; + data.currentVersion = step.toVersion; + await ledger.write(data); + applied.push({ ...entry }); + this.log.log( + 'info', + `smartmigration: step "${step.id}" applied in ${durationMs}ms`, + ); + } catch (err) { + const finishedAt = new Date(); + const durationMs = Date.now() - stepStart; + const error = err as Error; + entry = { + id: step.id, + fromVersion: step.fromVersion, + toVersion: step.toVersion, + status: 'failed', + startedAt: startedAt.toISOString(), + finishedAt: finishedAt.toISOString(), + durationMs, + error: { message: error.message, stack: error.stack }, + }; + // Persist failure to ledger so re-runs see it. + try { + data = await ledger.read(); + data.steps[step.id] = entry; + await ledger.write(data); + } catch { + // Ledger write failed — re-throw the original error anyway. + } + this.log.log( + 'error', + `smartmigration: step "${step.id}" failed after ${durationMs}ms: ${error.message}`, + ); + throw new SmartMigrationError( + 'STEP_FAILED', + `Migration step "${step.id}" (${step.fromVersion} → ${step.toVersion}) failed: ${error.message}`, + { stepId: step.id, originalError: error.message, stack: error.stack }, + ); + } + } + + const finalData = await ledger.read(); + return { + currentVersionBefore, + currentVersionAfter: finalData.currentVersion ?? this.settings.targetVersion, + targetVersion: this.settings.targetVersion, + wasUpToDate: false, + wasFreshInstall, + stepsApplied: applied, + stepsSkipped: [], + totalDurationMs: Date.now() - runStart, + }; + } finally { + await ledger.releaseLock(this.instanceId).catch((err) => { + this.log.log( + 'warn', + `smartmigration: failed to release lock: ${(err as Error).message}`, + ); + }); + } + } + + /** + * Resolve the plan against the current ledger state without acquiring a + * lock or executing anything. Used by `plan()` and `dryRun: true`. + */ + private computeResultWithoutRun(data: ISmartMigrationLedgerData): IMigrationRunResult { + const currentVersion = + data.currentVersion ?? + (this.steps.length > 0 ? this.steps[0].fromVersion : this.settings.targetVersion); + + if (VersionResolver.equals(currentVersion, this.settings.targetVersion)) { + return { + currentVersionBefore: data.currentVersion, + currentVersionAfter: currentVersion, + targetVersion: this.settings.targetVersion, + wasUpToDate: true, + wasFreshInstall: false, + stepsApplied: [], + stepsSkipped: [], + totalDurationMs: 0, + }; + } + + const plan = VersionResolver.computePlan( + this.steps, + currentVersion, + this.settings.targetVersion, + ); + + const skipped: IMigrationStepResult[] = plan.map((step) => ({ + id: step.id, + fromVersion: step.fromVersion, + toVersion: step.toVersion, + status: 'skipped' as const, + startedAt: '', + finishedAt: '', + durationMs: 0, + })); + + return { + currentVersionBefore: data.currentVersion, + currentVersionAfter: currentVersion, + targetVersion: this.settings.targetVersion, + wasUpToDate: false, + wasFreshInstall: false, + stepsApplied: [], + stepsSkipped: skipped, + totalDurationMs: 0, + }; + } + + private async ensureLedger(): Promise { + if (this.ledger) return this.ledger; + const ledgerName = this.settings.ledgerName; + if (this.settings.ledgerBackend === 'mongo') { + this.ledger = new MongoLedger(this.settings.db!, ledgerName); + } else { + this.ledger = new S3Ledger(this.settings.bucket!, ledgerName); + } + await this.ledger.init(); + return this.ledger; + } + + private async acquireLockWithBackoff(): Promise { + const ledger = await this.ensureLedger(); + const deadline = Date.now() + this.settings.lockWaitMs; + while (Date.now() <= deadline) { + const got = await ledger.acquireLock(this.instanceId, this.settings.lockTtlMs); + if (got) return true; + await this.sleep(LOCK_POLL_INTERVAL_MS); + } + return false; + } + + /** + * Heuristic fresh-install detector. Returns true when neither mongo nor S3 + * contain anything besides smartmigration's own ledger artifacts. + */ + private async detectFreshInstall(): Promise { + if (this.settings.db) { + const collections = await this.settings.db.mongoDb + .listCollections({}, { nameOnly: true }) + .toArray(); + const userCollections = collections.filter( + (c: { name: string }) => !this.isReservedCollectionName(c.name), + ); + if (userCollections.length > 0) return false; + } + if (this.settings.bucket) { + const cursor = (this.settings.bucket as any).createCursor('', { pageSize: 5 }); + const batch = (await cursor.next()) as string[] | undefined; + if (batch && batch.length > 0) { + const userKeys = batch.filter((k) => !k.startsWith('.smartmigration/')); + if (userKeys.length > 0) return false; + } + } + return true; + } + + private isReservedCollectionName(name: string): boolean { + // smartdata's EasyStore creates a collection named "SmartdataEasyStore". + return name === 'SmartdataEasyStore' || name.startsWith('system.'); + } + + private sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); + } +} diff --git a/ts/classes.versionresolver.ts b/ts/classes.versionresolver.ts new file mode 100644 index 0000000..a1f33c4 --- /dev/null +++ b/ts/classes.versionresolver.ts @@ -0,0 +1,176 @@ +import * as plugins from './plugins.js'; +import type { IMigrationStepDefinition } from './interfaces.js'; + +/** + * SmartMigrationError — thrown for all user-visible failures (validation, + * planning, lock acquisition, ledger I/O). The exact error site is encoded + * in `code` so callers can branch on it. + */ +export class SmartMigrationError extends Error { + public readonly code: string; + public readonly details?: Record; + constructor(code: string, message: string, details?: Record) { + super(message); + this.name = 'SmartMigrationError'; + this.code = code; + this.details = details; + } +} + +/** + * Wraps `@push.rocks/smartversion` to provide simple comparison helpers. + * All public methods accept and return plain semver strings. + */ +export class VersionResolver { + /** True iff `a` and `b` represent the same semver version. */ + public static equals(a: string, b: string): boolean { + // Uses SmartVersion.equalsString (added in @push.rocks/smartversion 3.1.0) + // which delegates to semver.eq under the hood. + return new plugins.smartversion.SmartVersion(a).equalsString(b); + } + + /** True iff `a < b` semver-wise. */ + public static lessThan(a: string, b: string): boolean { + return new plugins.smartversion.SmartVersion(a).lessThanString(b); + } + + /** True iff `a > b` semver-wise. */ + public static greaterThan(a: string, b: string): boolean { + return new plugins.smartversion.SmartVersion(a).greaterThanString(b); + } + + /** Throws if `version` is not a valid semver string. */ + public static assertValid(version: string, label: string): void { + try { + // Constructing SmartVersion throws if the string is invalid. + // eslint-disable-next-line no-new + new plugins.smartversion.SmartVersion(version); + } catch (err) { + throw new SmartMigrationError( + 'INVALID_VERSION', + `${label} is not a valid semver string: "${version}"`, + { version, label, cause: (err as Error).message }, + ); + } + } + + /** + * Validate the chain of registered steps: + * - ids are unique + * - from/to versions are valid semver + * - each step's from < to + * - each step's `from` strictly equals the previous step's `to` + */ + public static validateChain(steps: IMigrationStepDefinition[]): void { + const seenIds = new Set(); + for (let i = 0; i < steps.length; i++) { + const step = steps[i]; + + if (seenIds.has(step.id)) { + throw new SmartMigrationError( + 'DUPLICATE_STEP_ID', + `Migration step id "${step.id}" is registered more than once.`, + { stepId: step.id }, + ); + } + seenIds.add(step.id); + + this.assertValid(step.fromVersion, `step "${step.id}" fromVersion`); + this.assertValid(step.toVersion, `step "${step.id}" toVersion`); + + if (!this.lessThan(step.fromVersion, step.toVersion)) { + throw new SmartMigrationError( + 'NON_INCREASING_STEP', + `Migration step "${step.id}" has fromVersion "${step.fromVersion}" >= toVersion "${step.toVersion}". Steps must strictly upgrade.`, + { stepId: step.id, fromVersion: step.fromVersion, toVersion: step.toVersion }, + ); + } + + if (i > 0) { + const prev = steps[i - 1]; + if (!this.equals(prev.toVersion, step.fromVersion)) { + throw new SmartMigrationError( + 'CHAIN_GAP', + `Migration step "${step.id}" starts at "${step.fromVersion}", but the previous step "${prev.id}" ended at "${prev.toVersion}". Steps must form a contiguous chain in registration order.`, + { + prevStepId: prev.id, + prevToVersion: prev.toVersion, + stepId: step.id, + fromVersion: step.fromVersion, + }, + ); + } + } + } + } + + /** + * Compute which subset of `steps` should be executed to advance the data + * from `currentVersion` to `targetVersion`. + * + * Behavior: + * - If currentVersion === targetVersion → returns [] + * - Otherwise, finds the step whose `fromVersion === currentVersion` + * and returns it plus all subsequent steps up to (and including) + * the one whose `toVersion === targetVersion`. + * - If no step starts at currentVersion → throws CHAIN_NOT_AT_CURRENT. + * - If walking past targetVersion never matches → throws TARGET_NOT_REACHABLE. + * - If currentVersion > targetVersion → throws DOWNGRADE_NOT_SUPPORTED. + */ + public static computePlan( + steps: IMigrationStepDefinition[], + currentVersion: string, + targetVersion: string, + ): IMigrationStepDefinition[] { + this.assertValid(currentVersion, 'currentVersion'); + this.assertValid(targetVersion, 'targetVersion'); + + if (this.equals(currentVersion, targetVersion)) { + return []; + } + + if (this.greaterThan(currentVersion, targetVersion)) { + throw new SmartMigrationError( + 'DOWNGRADE_NOT_SUPPORTED', + `Current data version "${currentVersion}" is ahead of target version "${targetVersion}". smartmigration v1 does not support rollback.`, + { currentVersion, targetVersion }, + ); + } + + const startIndex = steps.findIndex((s) => this.equals(s.fromVersion, currentVersion)); + if (startIndex === -1) { + throw new SmartMigrationError( + 'CHAIN_NOT_AT_CURRENT', + `No registered migration step starts at the current data version "${currentVersion}". Registered chain: ${this.describeChain(steps)}`, + { currentVersion, registeredChain: steps.map((s) => `${s.fromVersion}→${s.toVersion}`) }, + ); + } + + const plan: IMigrationStepDefinition[] = []; + for (let i = startIndex; i < steps.length; i++) { + const step = steps[i]; + plan.push(step); + if (this.equals(step.toVersion, targetVersion)) { + return plan; + } + if (this.greaterThan(step.toVersion, targetVersion)) { + throw new SmartMigrationError( + 'TARGET_NOT_REACHABLE', + `Migration step "${step.id}" upgrades to "${step.toVersion}", which overshoots target "${targetVersion}". No exact-match step ends at the target.`, + { stepId: step.id, stepTo: step.toVersion, targetVersion }, + ); + } + } + + throw new SmartMigrationError( + 'TARGET_NOT_REACHABLE', + `Walked the entire registered chain from "${currentVersion}" but never reached target "${targetVersion}". Registered chain: ${this.describeChain(steps)}`, + { currentVersion, targetVersion, registeredChain: steps.map((s) => `${s.fromVersion}→${s.toVersion}`) }, + ); + } + + private static describeChain(steps: IMigrationStepDefinition[]): string { + if (steps.length === 0) return '(empty)'; + return steps.map((s) => `${s.id}(${s.fromVersion}→${s.toVersion})`).join(' → '); + } +} diff --git a/ts/index.ts b/ts/index.ts new file mode 100644 index 0000000..1400a91 --- /dev/null +++ b/ts/index.ts @@ -0,0 +1,21 @@ +/** + * @push.rocks/smartmigration — unified migration runner for MongoDB and S3. + */ + +export { SmartMigration, SmartMigrationError } from './classes.smartmigration.js'; +export { MigrationStepBuilder } from './classes.migrationstep.js'; +export { VersionResolver } from './classes.versionresolver.js'; + +export type { + ISmartMigrationOptions, + IMigrationContext, + IMigrationCheckpoint, + IMigrationStepInfo, + IMigrationStepDefinition, + IMigrationStepResult, + IMigrationLedgerEntry, + IMigrationRunResult, + ISmartMigrationLedgerData, +} from './interfaces.js'; + +export type { TMigrationStatus, TLedgerBackend } from './types.js'; diff --git a/ts/interfaces.ts b/ts/interfaces.ts new file mode 100644 index 0000000..7785e65 --- /dev/null +++ b/ts/interfaces.ts @@ -0,0 +1,169 @@ +import type * as plugins from './plugins.js'; +import type { TLedgerBackend, TMigrationStatus } from './types.js'; + +/** + * Constructor options for SmartMigration. + */ +export interface ISmartMigrationOptions { + /** Target version for the data. Typically the app's package.json version. */ + targetVersion: string; + + /** + * Optional smartdata instance. Required if any step uses ctx.db / ctx.mongo, + * and required if you want a mongo-backed ledger. + */ + db?: plugins.smartdata.SmartdataDb; + + /** + * Optional smartbucket Bucket. Required if any step uses ctx.bucket / ctx.s3, + * and required if you want an S3-backed ledger. + */ + bucket?: plugins.smartbucket.Bucket; + + /** Logical name for this migration ledger. Defaults to "smartmigration". */ + ledgerName?: string; + + /** Where to persist the ledger. Defaults to "mongo" if db provided, otherwise "s3". */ + ledgerBackend?: TLedgerBackend; + + /** + * For a fresh install (no ledger AND no app data), jump straight to this version + * instead of running every step from the earliest. Defaults to undefined, + * which means "run every step from earliest from-version". + */ + freshInstallVersion?: string; + + /** How long (ms) to wait for a stale lock from another instance. Default 60_000. */ + lockWaitMs?: number; + + /** How long (ms) before this instance's own lock auto-expires. Default 600_000. */ + lockTtlMs?: number; + + /** If true, run() returns the plan without executing anything. Default false. */ + dryRun?: boolean; + + /** Custom logger. Defaults to module logger. */ + logger?: plugins.smartlog.Smartlog; +} + +/** + * Information about a single step exposed to the migration handler via ctx.step. + */ +export interface IMigrationStepInfo { + id: string; + fromVersion: string; + toVersion: string; + description?: string; + isResumable: boolean; +} + +/** + * The context object passed into every step's `up()` handler. + */ +export interface IMigrationContext { + /** High-level smartdata instance. Present iff `db` was passed to the constructor. */ + db?: plugins.smartdata.SmartdataDb; + + /** High-level smartbucket Bucket. Present iff `bucket` was passed to the constructor. */ + bucket?: plugins.smartbucket.Bucket; + + /** Raw mongo `Db`. Present iff `db` was passed to the constructor. */ + mongo?: plugins.TRawMongoDb; + + /** Raw S3 client. Present iff `bucket` was passed to the constructor. */ + s3?: plugins.TRawS3Client; + + /** Metadata about the currently running step. */ + step: IMigrationStepInfo; + + /** Logger scoped to this run. */ + log: plugins.smartlog.Smartlog; + + /** True when run() was called with `dryRun: true`. */ + isDryRun: boolean; + + /** Only present when the step was marked `.resumable()`. */ + checkpoint?: IMigrationCheckpoint; + + /** Convenience for transactional mongo migrations. Throws if no db configured. */ + startSession(): plugins.TMongoClientSession; +} + +/** + * Per-step persistent key/value store, used by resumable migrations to + * record progress so a subsequent run can pick up where the previous one + * stopped. + */ +export interface IMigrationCheckpoint { + read(key: string): Promise; + write(key: string, value: T): Promise; + clear(): Promise; +} + +/** + * The serialized form of a migration step's outcome, as stored in the ledger. + */ +export interface IMigrationLedgerEntry { + id: string; + fromVersion: string; + toVersion: string; + status: TMigrationStatus; + startedAt: string; + finishedAt: string; + durationMs: number; + error?: { message: string; stack?: string }; +} + +/** + * Per-step result returned by run(). + */ +export interface IMigrationStepResult { + id: string; + fromVersion: string; + toVersion: string; + status: TMigrationStatus; + durationMs: number; + startedAt: string; + finishedAt: string; + error?: { message: string; stack?: string }; +} + +/** + * Result of a single call to SmartMigration.run() or .plan(). + */ +export interface IMigrationRunResult { + currentVersionBefore: string | null; + currentVersionAfter: string; + targetVersion: string; + wasUpToDate: boolean; + wasFreshInstall: boolean; + stepsApplied: IMigrationStepResult[]; + stepsSkipped: IMigrationStepResult[]; + totalDurationMs: number; +} + +/** + * The opaque definition of a registered step. Created by MigrationStepBuilder. + */ +export interface IMigrationStepDefinition { + id: string; + fromVersion: string; + toVersion: string; + description?: string; + isResumable: boolean; + handler: (ctx: IMigrationContext) => Promise; +} + +/** + * Internal: the shape of the data persisted in the ledger backend. + */ +export interface ISmartMigrationLedgerData { + currentVersion: string | null; + steps: Record; + lock: { + holder: string | null; + acquiredAt: string | null; + expiresAt: string | null; + }; + checkpoints: Record>; +} diff --git a/ts/ledgers/classes.ledger.ts b/ts/ledgers/classes.ledger.ts new file mode 100644 index 0000000..80808bc --- /dev/null +++ b/ts/ledgers/classes.ledger.ts @@ -0,0 +1,41 @@ +import type { + ISmartMigrationLedgerData, +} from '../interfaces.js'; + +/** + * Abstract ledger interface — both MongoLedger and S3Ledger implement this. + * + * Lifecycle: + * 1. `init()` — open the underlying store, create empty document if needed + * 2. `read()` — return the current ledger data + * 3. `write(data)` — overwrite the ledger with the given data + * 4. `acquireLock(holderId, ttlMs)` — best-effort lock; returns true on success + * 5. `releaseLock(holderId)` — clear the lock if we still hold it + * 6. `close()` — release any resources + * + * The ledger data is a single self-contained JSON-serializable object. + * Both backends store it as a single document (mongo via EasyStore, s3 via + * a single sidecar object). + */ +export abstract class Ledger { + public abstract init(): Promise; + public abstract read(): Promise; + public abstract write(data: ISmartMigrationLedgerData): Promise; + public abstract acquireLock(holderId: string, ttlMs: number): Promise; + public abstract releaseLock(holderId: string): Promise; + public abstract close(): Promise; +} + +/** Build a fresh, empty ledger document. */ +export function emptyLedgerData(): ISmartMigrationLedgerData { + return { + currentVersion: null, + steps: {}, + lock: { + holder: null, + acquiredAt: null, + expiresAt: null, + }, + checkpoints: {}, + }; +} diff --git a/ts/ledgers/classes.mongoledger.ts b/ts/ledgers/classes.mongoledger.ts new file mode 100644 index 0000000..ce8ccc1 --- /dev/null +++ b/ts/ledgers/classes.mongoledger.ts @@ -0,0 +1,106 @@ +import type * as plugins from '../plugins.js'; +import type { ISmartMigrationLedgerData } from '../interfaces.js'; +import { Ledger, emptyLedgerData } from './classes.ledger.js'; + +/** + * Mongo-backed ledger that persists `ISmartMigrationLedgerData` as a single + * document via smartdata's `EasyStore`. The EasyStore's nameId is + * `smartmigration:`, scoping multiple migration ledgers in the + * same database. + */ +export class MongoLedger extends Ledger { + private db: plugins.smartdata.SmartdataDb; + private ledgerName: string; + private easyStore: any | null = null; // EasyStore — typed loosely because the peer type may not be present at compile time + + constructor(db: plugins.smartdata.SmartdataDb, ledgerName: string) { + super(); + this.db = db; + this.ledgerName = ledgerName; + } + + public async init(): Promise { + this.easyStore = await this.db.createEasyStore(`smartmigration:${this.ledgerName}`); + // EasyStore creates an empty `data: {}` on first read. Hydrate it to the + // canonical empty shape so subsequent reads always return all fields. + const existing = (await this.easyStore.readAll()) as Partial; + if ( + existing.currentVersion === undefined || + existing.steps === undefined || + existing.lock === undefined || + existing.checkpoints === undefined + ) { + await this.easyStore.writeAll(emptyLedgerData()); + } + } + + public async read(): Promise { + if (!this.easyStore) { + throw new Error('MongoLedger.read() called before init()'); + } + const data = (await this.easyStore.readAll()) as ISmartMigrationLedgerData; + return this.normalize(data); + } + + public async write(data: ISmartMigrationLedgerData): Promise { + if (!this.easyStore) { + throw new Error('MongoLedger.write() called before init()'); + } + // Use EasyStore.replace (added in @push.rocks/smartdata 7.1.7) for true + // overwrite semantics. This lets us actually delete keys from + // checkpoints / steps when the in-memory ledger drops them — writeAll + // would merge and silently retain them. + await this.easyStore.replace(data); + } + + public async acquireLock(holderId: string, ttlMs: number): Promise { + const data = await this.read(); + const now = new Date(); + const lockHeld = data.lock.holder !== null; + const lockExpired = + data.lock.expiresAt !== null && new Date(data.lock.expiresAt).getTime() < now.getTime(); + + if (lockHeld && !lockExpired) { + return false; + } + + const expiresAt = new Date(now.getTime() + ttlMs); + data.lock = { + holder: holderId, + acquiredAt: now.toISOString(), + expiresAt: expiresAt.toISOString(), + }; + await this.write(data); + + // Re-read to confirm we won the race. EasyStore is last-writer-wins so + // this is a probabilistic CAS, not a true atomic CAS — adequate for v1. + const verify = await this.read(); + return verify.lock.holder === holderId; + } + + public async releaseLock(holderId: string): Promise { + const data = await this.read(); + if (data.lock.holder !== holderId) { + // Lock was stolen or never held — nothing to release. + return; + } + data.lock = { holder: null, acquiredAt: null, expiresAt: null }; + await this.write(data); + } + + public async close(): Promise { + // EasyStore has no explicit close — it just dereferences when the parent + // SmartdataDb closes. + this.easyStore = null; + } + + /** Fill in any missing top-level fields with their defaults. */ + private normalize(data: Partial): ISmartMigrationLedgerData { + return { + currentVersion: data.currentVersion ?? null, + steps: data.steps ?? {}, + lock: data.lock ?? { holder: null, acquiredAt: null, expiresAt: null }, + checkpoints: data.checkpoints ?? {}, + }; + } +} diff --git a/ts/ledgers/classes.s3ledger.ts b/ts/ledgers/classes.s3ledger.ts new file mode 100644 index 0000000..ad32797 --- /dev/null +++ b/ts/ledgers/classes.s3ledger.ts @@ -0,0 +1,92 @@ +import type * as plugins from '../plugins.js'; +import type { ISmartMigrationLedgerData } from '../interfaces.js'; +import { Ledger, emptyLedgerData } from './classes.ledger.js'; + +/** + * S3-backed ledger that persists `ISmartMigrationLedgerData` as a single + * JSON object at `/.smartmigration/.json`. + * + * Locking is best-effort: S3 has no conditional writes (without versioning + * + a separate index). Single-instance SaaS deployments are fine; multi- + * instance deployments should use the mongo ledger or provide external + * coordination. + */ +export class S3Ledger extends Ledger { + private bucket: plugins.smartbucket.Bucket; + private path: string; + + constructor(bucket: plugins.smartbucket.Bucket, ledgerName: string) { + super(); + this.bucket = bucket; + this.path = `.smartmigration/${ledgerName}.json`; + } + + public async init(): Promise { + const exists = await (this.bucket as any).fastExists({ path: this.path }); + if (!exists) { + await this.write(emptyLedgerData()); + } + } + + public async read(): Promise { + const buffer = await (this.bucket as any).fastGet({ path: this.path }); + const data = JSON.parse(buffer.toString('utf8')) as Partial; + return this.normalize(data); + } + + public async write(data: ISmartMigrationLedgerData): Promise { + const json = JSON.stringify(data, null, 2); + await (this.bucket as any).fastPut({ + path: this.path, + contents: json, + overwrite: true, + }); + } + + public async acquireLock(holderId: string, ttlMs: number): Promise { + const data = await this.read(); + const now = new Date(); + const lockHeld = data.lock.holder !== null; + const lockExpired = + data.lock.expiresAt !== null && new Date(data.lock.expiresAt).getTime() < now.getTime(); + + if (lockHeld && !lockExpired) { + return false; + } + + const expiresAt = new Date(now.getTime() + ttlMs); + data.lock = { + holder: holderId, + acquiredAt: now.toISOString(), + expiresAt: expiresAt.toISOString(), + }; + await this.write(data); + + // Re-read to detect races. Best-effort only. + const verify = await this.read(); + return verify.lock.holder === holderId; + } + + public async releaseLock(holderId: string): Promise { + const data = await this.read(); + if (data.lock.holder !== holderId) { + return; + } + data.lock = { holder: null, acquiredAt: null, expiresAt: null }; + await this.write(data); + } + + public async close(): Promise { + // No persistent connection to release; the smartbucket Bucket lives on + // the user's SmartBucket instance. + } + + private normalize(data: Partial): ISmartMigrationLedgerData { + return { + currentVersion: data.currentVersion ?? null, + steps: data.steps ?? {}, + lock: data.lock ?? { holder: null, acquiredAt: null, expiresAt: null }, + checkpoints: data.checkpoints ?? {}, + }; + } +} diff --git a/ts/logger.ts b/ts/logger.ts new file mode 100644 index 0000000..a38b160 --- /dev/null +++ b/ts/logger.ts @@ -0,0 +1,19 @@ +import * as plugins from './plugins.js'; + +/** + * Module-scoped Smartlog singleton. Users may pass their own logger via + * `ISmartMigrationOptions.logger` to override this default. + */ +export const logger = new plugins.smartlog.Smartlog({ + logContext: { + company: 'Lossless GmbH', + companyunit: 'push.rocks', + containerName: 'smartmigration', + environment: 'production', + runtime: 'node', + zone: 'pushrocks', + }, + minimumLogLevel: 'info', +}); + +logger.addLogDestination(new plugins.smartlogDestinationLocal.DestinationLocal()); diff --git a/ts/plugins.ts b/ts/plugins.ts new file mode 100644 index 0000000..55b08a0 --- /dev/null +++ b/ts/plugins.ts @@ -0,0 +1,25 @@ +// node native scope +import { randomUUID } from 'node:crypto'; +export { randomUUID }; + +// pushrocks scope +import * as smartlog from '@push.rocks/smartlog'; +import * as smartlogDestinationLocal from '@push.rocks/smartlog/destination-local'; +import * as smartversion from '@push.rocks/smartversion'; +export { smartlog, smartlogDestinationLocal, smartversion }; + +// optional pushrocks peers — type-only imports so the module compiles even +// when end users only install one of them. The type-import loads the .d.ts +// at compile time but emits no runtime require/import. Both packages are +// devDeps locally so the build can resolve them. +import type * as smartdata from '@push.rocks/smartdata'; +import type * as smartbucket from '@push.rocks/smartbucket'; +export type { smartdata, smartbucket }; + +// Driver types are derived from the smartdata / smartbucket public surface +// to avoid having to declare `mongodb` or `@aws-sdk/client-s3` as direct +// dependencies. These aliases are exported for use in the public interfaces. +export type TRawMongoDb = smartdata.SmartdataDb['mongoDb']; +export type TRawMongoClient = smartdata.SmartdataDb['mongoDbClient']; +export type TMongoClientSession = ReturnType; +export type TRawS3Client = smartbucket.SmartBucket['storageClient']; diff --git a/ts/types.ts b/ts/types.ts new file mode 100644 index 0000000..860d6c7 --- /dev/null +++ b/ts/types.ts @@ -0,0 +1,9 @@ +/** + * Status of a migration step in a run result. + */ +export type TMigrationStatus = 'applied' | 'skipped' | 'failed'; + +/** + * Backend used to persist the migration ledger. + */ +export type TLedgerBackend = 'mongo' | 's3'; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3e813bb --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "esModuleInterop": true, + "verbatimModuleSyntax": true, + "types": ["node"] + }, + "exclude": ["dist_*/**/*.d.ts"] +}