diff --git a/package.json b/package.json index 02a196b..fcb3890 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "dependencies": { "@json2csv/node": "^7.0.6", "@prisma/client": "^6.19.1", + "@stellar/stellar-base": "^15.0.0", "@types/js-yaml": "^4.0.9", "@types/pdfkit": "^0.17.3", "@types/puppeteer": "^5.4.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4dfc522..ad1d927 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,15 +1,15 @@ lockfileVersion: '9.0' settings: - autoInstallPeers: true - excludeLinksFromLockfile: false + autoInstallPeers: true + excludeLinksFromLockfile: false importers: .: dependencies: '@json2csv/node': specifier: ^7.0.6 - version: 7.0.7 + version: 7.0.8 '@prisma/client': specifier: ^6.19.1 version: 6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3) @@ -36,7 +36,7 @@ importers: version: 5.6.2 cloudinary: specifier: ^2.8.0 - version: 2.10.0 + version: 2.10.1 cors: specifier: ^2.8.5 version: 2.8.6 @@ -48,7 +48,7 @@ importers: version: 5.2.1 express-rate-limit: specifier: ^8.2.1 - version: 8.6.1(express@5.2.1) + version: 8.6.2(express@5.2.1) google-auth-library: specifier: ^10.5.0 version: 10.9.1 @@ -56,8 +56,8 @@ importers: specifier: ^8.1.0 version: 8.3.0 ioredis: - specifier: ^5.11.1 - version: 5.11.1 + specifier: ^6.0.0 + version: 6.0.0 jsonwebtoken: specifier: ^9.0.3 version: 9.0.3 @@ -84,7 +84,7 @@ importers: version: 24.43.1(typescript@5.9.3) resend: specifier: ^6.4.2 - version: 6.18.1 + version: 6.24.0 sharp: specifier: ^0.34.1 version: 0.34.5 @@ -100,9 +100,6 @@ importers: tspec: specifier: ^0.1.116 version: 0.1.120(@types/express@5.0.6)(express@5.2.1) - uuid: - specifier: ^14.0.1 - version: 14.0.1 xlsx: specifier: ^0.18.5 version: 0.18.5 @@ -128,9 +125,6 @@ importers: '@types/helmet': specifier: ^4.0.0 version: 4.0.0 - '@types/ioredis': - specifier: ^5.0.0 - version: 5.0.0 '@types/jest': specifier: ^30.0.0 version: 30.0.0 @@ -161,15 +155,12 @@ importers: '@types/text-to-svg': specifier: ^3.1.4 version: 3.1.4 - '@types/uuid': - specifier: ^11.0.0 - version: 11.0.0 '@typescript-eslint/eslint-plugin': specifier: ^8.32.0 - version: 8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + version: 8.68.0(@typescript-eslint/parser@8.68.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/parser': specifier: ^8.32.0 - version: 8.65.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + version: 8.68.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) eslint: specifier: ^9.26.0 version: 9.39.5(jiti@2.7.0) @@ -852,10 +843,10 @@ packages: cpu: [x64] os: [win32] - '@ioredis/commands@1.10.0': + '@ioredis/commands@2.0.0': resolution: { - integrity: sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==, + integrity: sha512-vrx0AE/T0h7cRZwfo1M39Cr+ZhZrkf0V8mQN75wucKCxCLD9l/VX6no3gFvrLqD1IlG/1LtzWovqEw3t0Vr9zg==, } '@isaacs/cliui@8.0.2': @@ -1059,33 +1050,33 @@ packages: integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==, } - '@json2csv/formatters@7.0.7': + '@json2csv/formatters@7.0.8': resolution: { - integrity: sha512-Sm0F11FKnTouBVYqW0Sp+/P7ECapfAEw0p0L6lz0z6q3I6CVQjFnQ8m20g3KlJvYq+y4G9m56QZHAWiUxIJlRA==, + integrity: sha512-YYpeZF7qKSX55FMYEl0m7Hn188l050k171/KwDHSMPHLHvWxDbzjmH1qVfXyV7XO7MMpDx1P7xksd/jXqlLxDw==, } - '@json2csv/node@7.0.7': + '@json2csv/node@7.0.8': resolution: { - integrity: sha512-sP5BaTx/MyoY+UdHlOnBiWB2PF3i8Gw6PL7ld++L9r6bU4X2N1AahS1m1PO/bTElboSswSwrsE6J1XHhlpZ+0g==, + integrity: sha512-Vy5Mq6Zl5rBkrFFqnb12PjsQJJz470PxGji1q1n1fah/LhVyQY6fqKJb1fd2d+KlJgVQ8K9d5U2zrBJkCFNoMA==, } - '@json2csv/plainjs@7.0.7': + '@json2csv/plainjs@7.0.8': resolution: { - integrity: sha512-aJWN+HrOp1YQaA/fnYtTDlc24ZNRfUlu5ercUPyggxE8tq90Pd88dCdX/aj+BRiLB+/6UZyRbCIkFj0/iBPMgw==, + integrity: sha512-bxsdb7tcHFyq6SGvDdHrxgSLxc8ScNyX+6B1aT+Anp8PEieZIenf6lPIJ2CnB4MQkrNANfFj6mXJlK9f8Bh5wg==, } - '@napi-rs/wasm-runtime@1.2.2': + '@napi-rs/wasm-runtime@1.2.3': resolution: { - integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==, + integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==, } engines: { node: ^20.19.0 || ^22.13.0 || >=23.5.0 } peerDependencies: - '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.3 - '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.3 + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 '@noble/curves@1.9.7': resolution: @@ -1237,10 +1228,10 @@ packages: engines: { node: '>=20.0.0' } deprecated: This package is now rolled into @stellar/stellar-sdk. Please use @stellar/stellar-sdk to continue receiving updates and support. - '@streamparser/json@0.0.22': + '@streamparser/json@0.0.23': resolution: { - integrity: sha512-b6gTSBjJ8G8SuO3Gbbj+zXbVx8NSs1EbpbMKpzGLWMdkR+98McH9bEjSz3+0mPJf68c5nxa3CrJHp5EQNXM6zQ==, + integrity: sha512-givIVGxVGwP2oh5wiGdjQBKLZAS6LMkvnOxKybKTZDWP9LCO20eAzAL8OkUg8iR7u28cB2Ti7lFfLHnAAZGN6A==, } '@swc/helpers@0.5.23': @@ -1255,10 +1246,10 @@ packages: integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==, } - '@tsconfig/node10@1.0.12': + '@tsconfig/node10@1.0.13': resolution: { - integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==, + integrity: sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==, } '@tsconfig/node12@1.0.11': @@ -1383,13 +1374,6 @@ packages: integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==, } - '@types/ioredis@5.0.0': - resolution: - { - integrity: sha512-zJbJ3FVE17CNl5KXzdeSPtdltc4tMT3TzC6fxQS0sQngkbFZ6h+0uTafsRqu+eSLIugf6Yb0Ea0SUuRr42Nk9g==, - } - deprecated: This is a stub types definition. ioredis provides its own type definitions, so you do not need this installed. - '@types/istanbul-lib-coverage@2.0.6': resolution: { @@ -1552,13 +1536,6 @@ packages: integrity: sha512-nupWR3fOC2CaakVDvnEuiNpcg+XZD8ez7yJf7HCcpR1JKqPKxnUqeFH8er9txouyCbsdwXjhKKpMPtnpQZYCsQ==, } - '@types/uuid@11.0.0': - resolution: - { - integrity: sha512-HVyk8nj2m+jcFRNazzqyVKiZezyhDKrGUA3jlEcg/nZ6Ms+qHwocba1Y/AaVaznJTAM9xpdFSh+ptbNrhOGvZA==, - } - deprecated: This is a stub types definition. uuid provides its own type definitions, so you do not need this installed. - '@types/xlsx@0.0.35': resolution: { @@ -1583,99 +1560,99 @@ packages: integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==, } - '@typescript-eslint/eslint-plugin@8.65.0': + '@typescript-eslint/eslint-plugin@8.68.0': resolution: { - integrity: sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==, + integrity: sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: - '@typescript-eslint/parser': ^8.65.0 + '@typescript-eslint/parser': ^8.68.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.65.0': + '@typescript-eslint/parser@8.68.0': resolution: { - integrity: sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==, + integrity: sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.65.0': + '@typescript-eslint/project-service@8.68.0': resolution: { - integrity: sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==, + integrity: sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.65.0': + '@typescript-eslint/scope-manager@8.68.0': resolution: { - integrity: sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==, + integrity: sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - '@typescript-eslint/tsconfig-utils@8.65.0': + '@typescript-eslint/tsconfig-utils@8.68.0': resolution: { - integrity: sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==, + integrity: sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.65.0': + '@typescript-eslint/type-utils@8.68.0': resolution: { - integrity: sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==, + integrity: sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.65.0': + '@typescript-eslint/types@8.68.0': resolution: { - integrity: sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==, + integrity: sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - '@typescript-eslint/typescript-estree@8.65.0': + '@typescript-eslint/typescript-estree@8.68.0': resolution: { - integrity: sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==, + integrity: sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.65.0': + '@typescript-eslint/utils@8.68.0': resolution: { - integrity: sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==, + integrity: sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.65.0': + '@typescript-eslint/visitor-keys@8.68.0': resolution: { - integrity: sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==, + integrity: sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - '@ungap/structured-clone@1.3.3': + '@ungap/structured-clone@1.3.4': resolution: { - integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==, + integrity: sha512-JL+CF0GeLHyPWI0rXu7UnxgiuOm9UQWzadi0OYOJNhNO2q6EZElpwlgXkNkfU1PzANDHq3YcwKVZprdvS+BrbQ==, } '@unrs/resolver-binding-android-arm-eabi@1.12.2': @@ -1942,10 +1919,10 @@ packages: } engines: { node: '>=8' } - ansi-regex@6.2.2: + ansi-regex@6.3.0: resolution: { - integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==, + integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==, } engines: { node: '>=12' } @@ -2098,10 +2075,10 @@ packages: } engines: { node: 18 || 20 || >=22 } - bare-events@2.9.1: + bare-events@2.9.2: resolution: { - integrity: sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==, + integrity: sha512-AIPKioV7/Y/8KfZ3AAhjPJxLLbY49S64Ym5DakZlUg75qQiTgUq9hEJoEwa4eUezPUlXRy/i5NpsKvo9jgKmoA==, } peerDependencies: bare-abort-controller: '*' @@ -2109,12 +2086,12 @@ packages: bare-abort-controller: optional: true - bare-fs@4.7.4: + bare-fs@4.8.1: resolution: { - integrity: sha512-y1kC+ffIx/tPLdTE693uNjHfzTfr+ravR5tvWlMXe25nELbkqV400S71qHDwbkAQ1FVEZobB1NFRzFbCCcyBCQ==, + integrity: sha512-N1nnXdHZAOSstz0XiHikGS4HGMH4CnSwhqWdGQQMqqdvp4Jybm9sE3R1WVnpWVd4SFkc8ryPDBLViNLwiEqECg==, } - engines: { bare: '>=1.16.0' } + engines: { bare: '>=1.28.0' } peerDependencies: bare-buffer: '*' peerDependenciesMeta: @@ -2127,10 +2104,10 @@ packages: integrity: sha512-JprUlveX3QjApC1cTpsUOiscADftCGVWkzitbHsRqv84hzYwYHw2mbluddsq5TvI8mH/8Ov1f4BiMAdcB0oYnQ==, } - bare-stream@2.13.3: + bare-stream@2.13.4: resolution: { - integrity: sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ==, + integrity: sha512-PcrQ8lVLbiJscNm1Kez+Yp4Gy4AHGcN1lzwjvf5NybWen7VvEgUfyfnXYJ2zNqWnzOfCb1Abq6lH8ti0syQszA==, } peerDependencies: bare-abort-controller: '*' @@ -2144,10 +2121,10 @@ packages: bare-events: optional: true - bare-url@2.4.6: + bare-url@2.5.2: resolution: { - integrity: sha512-iQxPClE07hETVpbRoX7JXX3v/ZQViCxe/SYCxylRLzdEx1xJAufPptfiOqR8tqiCtmbtMDANKWszzjLu1PMAZQ==, + integrity: sha512-L13PCJzKG8RGvx8V1/DdMi12ERhC3tprr7/8a94BxpmnRsFqxh5XZNdhtMxu5HPkRshYOOWRGY8lDP7ZhpG9Cg==, } base32.js@0.1.0: @@ -2170,10 +2147,10 @@ packages: integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, } - baseline-browser-mapping@2.11.10: + baseline-browser-mapping@2.11.19: resolution: { - integrity: sha512-35JEvJ5/KKlbCHjMCsONI2w6HE88STjVdHk+C7d8LtcFxUjZR1KeLP9izofn2qs0KUxX5r4z73bwH/rd+JHacw==, + integrity: sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw==, } engines: { node: '>=6.0.0' } hasBin: true @@ -2257,10 +2234,10 @@ packages: integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==, } - browserslist@4.28.7: + browserslist@4.28.8: resolution: { - integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==, + integrity: sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==, } engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } hasBin: true @@ -2375,10 +2352,10 @@ packages: } engines: { node: '>=10' } - caniuse-lite@1.0.30001806: + caniuse-lite@1.0.30001810: resolution: { - integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==, + integrity: sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==, } cfb@1.2.2: @@ -2450,10 +2427,10 @@ packages: integrity: sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==, } - cjs-module-lexer@2.2.0: + cjs-module-lexer@2.2.1: resolution: { - integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==, + integrity: sha512-Ca8swihM+/4yKecYHY52kgJd300hi2lADU/a1RxNTRe+RJ9jvqQlESpbz9DnG9mowez8qwXHB8qYdIUw9e+F5Q==, } cli-cursor@5.0.0: @@ -2484,10 +2461,10 @@ packages: } engines: { node: '>=0.8' } - cloudinary@2.10.0: + cloudinary@2.10.1: resolution: { - integrity: sha512-sY09kYg7wprkndAOjZBAYqFZqwL+SxnEGcAvksOvFA+5upnFn949UjkEkHKNSwkBtW/xRDd0p6NgbSXZcxkI3w==, + integrity: sha512-0aqF/sGwm2dSM/Xse87EI5OpKcuX/hwoPPdUDTdUal6GMPKevtElcI3spcaeuzJJbcLkY3vJaF22q0u50VO5Lw==, } engines: { node: '>=9' } @@ -2610,10 +2587,10 @@ packages: } engines: { node: '>= 0.6' } - content-type@2.0.0: + content-type@2.1.0: resolution: { - integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==, + integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==, } engines: { node: '>=18' } @@ -2694,6 +2671,7 @@ packages: { integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==, } + deprecated: Active development of CryptoJS has been discontinued. This library is no longer maintained. data-uri-to-buffer@4.0.1: resolution: @@ -2900,10 +2878,10 @@ packages: integrity: sha512-PPN80qRokCd1f015IANNhrwOnLO7GrrMQfk4/lnZRE/8j7UPWrNNjPV0uBrZutI/nHzernbW+J0hdqQysHiSnQ==, } - electron-to-chromium@1.5.399: + electron-to-chromium@1.5.415: resolution: { - integrity: sha512-lEcqhErbHjXRvd41rnWLpzbyU/IXfIYo7QwaFWmxGeLiLyY2TBCdHnWY88vB+p3ubnihRypDm66panXl7TylLA==, + integrity: sha512-958V+Kbhtgz+SxXeEVKBjrlKRBIDAYvUJfwhjxMZ5S6ut9jAl7l9ZKBkBrvjyjZE36PabLUo2L8kEeV5O4vgJg==, } emittery@0.13.1: @@ -3068,6 +3046,7 @@ packages: integrity: sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==, } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true peerDependencies: jiti: '*' @@ -3171,10 +3150,10 @@ packages: } engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } - express-rate-limit@8.6.1: + express-rate-limit@8.6.2: resolution: { - integrity: sha512-0D493aP61w0TJ2A0wy27riRsO7FMQ7FK+KUHOKCSfPvYo0R55aiC6emCVgFUeShH0fq0ICPVzNcgoS+BsbXQCA==, + integrity: sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A==, } engines: { node: '>= 16' } peerDependencies: @@ -3256,10 +3235,10 @@ packages: integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==, } - fast-uri@3.1.5: + fast-uri@3.1.6: resolution: { - integrity: sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==, + integrity: sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==, } fb-watchman@2.0.2: @@ -3435,10 +3414,10 @@ packages: integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, } - gaxios@7.3.0: + gaxios@7.3.1: resolution: { - integrity: sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==, + integrity: sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==, } engines: { node: '>=18' } @@ -3804,17 +3783,17 @@ packages: integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, } - ioredis@5.11.1: + ioredis@6.0.0: resolution: { - integrity: sha512-ehuGcf94bQXhfagULNXrJdfnWO38v070jxSx/qE87Kjzmu2fU7ro5EFAb+OPituLqgfyuQaym5DlrNydW2sJ9A==, + integrity: sha512-f+Dtubxfpf6KYFq7WVXJoOLn0bk4TJrMrN9SzeE+jrWrCWj7XX3fA6vkryafhADX+GMymRxgDJDOI33COkJc0w==, } - engines: { node: '>=12.22.0' } + engines: { node: '>=20.0.0' } - ip-address@10.4.0: + ip-address@10.5.0: resolution: { - integrity: sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==, + integrity: sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==, } engines: { node: '>= 12' } @@ -4701,12 +4680,12 @@ packages: integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, } - negotiator@1.0.0: + negotiator@1.1.0: resolution: { - integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==, + integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==, } - engines: { node: '>= 0.6' } + engines: { node: '>=18' } neo-async@2.6.2: resolution: @@ -4721,10 +4700,10 @@ packages: } engines: { node: '>= 0.4.0' } - node-addon-api@8.9.1: + node-addon-api@8.9.2: resolution: { - integrity: sha512-4eUQWVPCUUUiBjLnHS3cXWeC6ryoPUc0U3rP7IuzapoGbzMqd/r6KKO0clr0b+snQhsrueFEhCZDdK+LK7hxKg==, + integrity: sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg==, } engines: { node: ^18 || ^20 || >= 21 } @@ -4762,10 +4741,10 @@ packages: integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==, } - node-releases@2.0.51: + node-releases@2.0.53: resolution: { - integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==, + integrity: sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==, } engines: { node: '>=18' } @@ -4827,10 +4806,10 @@ packages: } engines: { node: '>= 0.4' } - ohash@2.0.11: + ohash@2.0.12: resolution: { - integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==, + integrity: sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==, } on-exit-leak-free@2.1.2: @@ -5080,10 +5059,10 @@ packages: } engines: { node: '>=8.6' } - picomatch@4.0.5: + picomatch@4.0.7: resolution: { - integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==, + integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==, } engines: { node: '>=12' } @@ -5365,13 +5344,6 @@ packages: } engines: { node: '>=4' } - redis-parser@3.0.0: - resolution: - { - integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==, - } - engines: { node: '>=4' } - require-directory@2.1.1: resolution: { @@ -5392,10 +5364,10 @@ packages: integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==, } - resend@6.18.1: + resend@6.24.0: resolution: { - integrity: sha512-XN8XIaDdKF+ziSQ3K23ndUcyhP7U3ze2gky6SPgYkuAOq54mH4Wdhwm7QylEQ3zlz0NzdX7/l1AgmJUZbdPI/Q==, + integrity: sha512-ZG+tRzTtg3usrzMMVK1THPILCDbxE0uefG3XEQro/+jb9hcRb8JiQeyzIo2BphMJk2OomBeciZU3rCgX3XWx5w==, } engines: { node: '>=20' } peerDependencies: @@ -5715,10 +5687,10 @@ packages: } engines: { node: '>=10.0.0' } - streamx@2.28.0: + streamx@2.28.1: resolution: { - integrity: sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==, + integrity: sha512-zEzXb0s5Cds7tqMH6rhZ05lcJydCWiQPEwiNngVqzsxCc962vLY4Uw+mW7od8kDH258k2Uz/JrOkdIAAhSh9VA==, } string-argv@0.3.2: @@ -5860,10 +5832,10 @@ packages: engines: { node: '>=20.0.0' } hasBin: true - swagger-ui-dist@5.32.11: + swagger-ui-dist@5.32.14: resolution: { - integrity: sha512-NEZzRuxHHQkbG3GCjNbzz+XRDoM7AztnXyzc2VCW5RXUvZBDW7bb3W29/SPfvav3yOzqnDTOLP2Xzbjxo0bldQ==, + integrity: sha512-nOA2pSQhcmODMUQZpJHYKNuwniDUqcOWGNaSCOoZv12FdOSJ9JxV95HtyRGNMqEBj6h6lCNTy20TgZDYTSuUIg==, } swagger-ui-express@4.6.3: @@ -5897,10 +5869,10 @@ packages: integrity: sha512-/hU4AXnIdZu+Gvl1pk0oI5f5HxWsCJRtY2aFaJdk9VvyL48DWU6iU5WAIPG+wIi1YvWA6eTJvIviP/tMAZZNwQ==, } - tar-stream@3.2.0: + tar-stream@3.2.1: resolution: { - integrity: sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==, + integrity: sha512-nqsEO8zLZJvrOMdEwkA0QdCLFbetHMn95Zqu4fKwX+hkaTWJPZZOrxx/PwtxoK0MMGQmBQNRW3CPs8IFYQz4cQ==, } teex@1.0.1: @@ -6204,10 +6176,10 @@ packages: integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==, } - update-browserslist-db@1.2.3: + update-browserslist-db@1.3.1: resolution: { - integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==, + integrity: sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==, } hasBin: true peerDependencies: @@ -6225,13 +6197,6 @@ packages: integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, } - uuid@14.0.1: - resolution: - { - integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==, - } - hasBin: true - v8-compile-cache-lib@3.0.1: resolution: { @@ -6347,10 +6312,10 @@ packages: } engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } - ws@8.21.1: + ws@8.21.3: resolution: { - integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==, + integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==, } engines: { node: '>=10.0.0' } peerDependencies: @@ -6455,1529 +6420,1562 @@ packages: } snapshots: + '@apidevtools/json-schema-ref-parser@14.0.1': + dependencies: + '@types/json-schema': 7.0.15 + js-yaml: 4.3.1 - '@apidevtools/json-schema-ref-parser@9.1.2': - dependencies: - '@jsdevtools/ono': 7.1.3 - '@types/json-schema': 7.0.15 - call-me-maybe: 1.0.2 - js-yaml: 4.1.1 - - '@apidevtools/openapi-schemas@2.1.0': {} - - '@apidevtools/swagger-methods@3.0.2': {} - - '@apidevtools/swagger-parser@10.0.3(openapi-types@12.1.3)': - dependencies: - '@apidevtools/json-schema-ref-parser': 9.1.2 - '@apidevtools/openapi-schemas': 2.1.0 - '@apidevtools/swagger-methods': 3.0.2 - '@jsdevtools/ono': 7.1.3 - call-me-maybe: 1.0.2 - openapi-types: 12.1.3 - z-schema: 5.0.5 - - '@babel/code-frame@7.29.0': - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/compat-data@7.29.0': {} - - '@babel/core@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.29.2 - '@babel/parser': 7.29.2 - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@5.5.0) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.29.1': - dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/helper-compilation-targets@7.28.6': - dependencies: - '@babel/compat-data': 7.29.0 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.1 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-globals@7.28.0': {} - - '@babel/helper-module-imports@7.28.6': - dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.28.6': {} - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.28.5': {} - - '@babel/helper-validator-option@7.27.1': {} - - '@babel/helpers@7.29.2': - dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - - '@babel/parser@7.29.2': - dependencies: - '@babel/types': 7.29.0 - - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/template@7.28.6': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - - '@babel/traverse@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.2 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - debug: 4.4.3(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/types@7.29.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - - '@bcoe/v8-coverage@0.2.3': {} - - '@cloudflare/json-schema-walker@0.1.1': {} - - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - - '@emnapi/core@1.9.1': - dependencies: - '@emnapi/wasi-threads': 1.2.0 - tslib: 2.8.1 - optional: true - - '@emnapi/runtime@1.9.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@emnapi/wasi-threads@1.2.0': - dependencies: - tslib: 2.8.1 - optional: true - - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1))': - dependencies: - eslint: 9.39.4(jiti@2.6.1) - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.2': {} - - '@eslint/config-array@0.21.2': - dependencies: - '@eslint/object-schema': 2.1.7 - debug: 4.4.3(supports-color@5.5.0) - minimatch: 3.1.5 - transitivePeerDependencies: - - supports-color - - '@eslint/config-helpers@0.4.2': - dependencies: - '@eslint/core': 0.17.0 - - '@eslint/core@0.17.0': - dependencies: - '@types/json-schema': 7.0.15 - - '@eslint/eslintrc@3.3.5': - dependencies: - ajv: 6.14.0 - debug: 4.4.3(supports-color@5.5.0) - espree: 10.4.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.1.1 - minimatch: 3.1.5 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@9.39.4': {} - - '@eslint/object-schema@2.1.7': {} - - '@eslint/plugin-kit@0.4.1': - dependencies: - '@eslint/core': 0.17.0 - levn: 0.4.1 - - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.7': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.4.3 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.4.3': {} - - '@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.1 - 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 - - '@ioredis/commands@2.0.0': {} - - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.2.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - - '@istanbuljs/load-nyc-config@1.1.0': - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.2 - resolve-from: 5.0.0 - - '@istanbuljs/schema@0.1.3': {} - - '@jest/console@30.3.0': - dependencies: - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - chalk: 4.1.2 - jest-message-util: 30.3.0 - jest-util: 30.3.0 - slash: 3.0.0 - - '@jest/core@30.3.0(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3))': - dependencies: - '@jest/console': 30.3.0 - '@jest/pattern': 30.0.1 - '@jest/reporters': 30.3.0 - '@jest/test-result': 30.3.0 - '@jest/transform': 30.3.0 - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 4.4.0 - exit-x: 0.2.2 - graceful-fs: 4.2.11 - jest-changed-files: 30.3.0 - jest-config: 30.3.0(@types/node@22.19.15)(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3)) - jest-haste-map: 30.3.0 - jest-message-util: 30.3.0 - jest-regex-util: 30.0.1 - jest-resolve: 30.3.0 - jest-resolve-dependencies: 30.3.0 - jest-runner: 30.3.0 - jest-runtime: 30.3.0 - jest-snapshot: 30.3.0 - jest-util: 30.3.0 - jest-validate: 30.3.0 - jest-watcher: 30.3.0 - pretty-format: 30.3.0 - slash: 3.0.0 - transitivePeerDependencies: - - babel-plugin-macros - - esbuild-register - - supports-color - - ts-node - - '@jest/diff-sequences@30.3.0': {} - - '@jest/environment@30.3.0': - dependencies: - '@jest/fake-timers': 30.3.0 - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - jest-mock: 30.3.0 - - '@jest/expect-utils@30.3.0': - dependencies: - '@jest/get-type': 30.1.0 - - '@jest/expect@30.3.0': - dependencies: - expect: 30.3.0 - jest-snapshot: 30.3.0 - transitivePeerDependencies: - - supports-color - - '@jest/fake-timers@30.3.0': - dependencies: - '@jest/types': 30.3.0 - '@sinonjs/fake-timers': 15.1.1 - '@types/node': 22.19.15 - jest-message-util: 30.3.0 - jest-mock: 30.3.0 - jest-util: 30.3.0 - - '@jest/get-type@30.1.0': {} - - '@jest/globals@30.3.0': - dependencies: - '@jest/environment': 30.3.0 - '@jest/expect': 30.3.0 - '@jest/types': 30.3.0 - jest-mock: 30.3.0 - transitivePeerDependencies: - - supports-color - - '@jest/pattern@30.0.1': - dependencies: - '@types/node': 22.19.15 - jest-regex-util: 30.0.1 - - '@jest/reporters@30.3.0': - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 30.3.0 - '@jest/test-result': 30.3.0 - '@jest/transform': 30.3.0 - '@jest/types': 30.3.0 - '@jridgewell/trace-mapping': 0.3.31 - '@types/node': 22.19.15 - chalk: 4.1.2 - collect-v8-coverage: 1.0.3 - exit-x: 0.2.2 - glob: 10.5.0 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6 - istanbul-reports: 3.2.0 - jest-message-util: 30.3.0 - jest-util: 30.3.0 - jest-worker: 30.3.0 - slash: 3.0.0 - string-length: 4.0.2 - v8-to-istanbul: 9.3.0 - transitivePeerDependencies: - - supports-color - - '@jest/schemas@30.0.5': - dependencies: - '@sinclair/typebox': 0.34.49 - - '@jest/snapshot-utils@30.3.0': - dependencies: - '@jest/types': 30.3.0 - chalk: 4.1.2 - graceful-fs: 4.2.11 - natural-compare: 1.4.0 - - '@jest/source-map@30.0.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - callsites: 3.1.0 - graceful-fs: 4.2.11 - - '@jest/test-result@30.3.0': - dependencies: - '@jest/console': 30.3.0 - '@jest/types': 30.3.0 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.3 - - '@jest/test-sequencer@30.3.0': - dependencies: - '@jest/test-result': 30.3.0 - graceful-fs: 4.2.11 - jest-haste-map: 30.3.0 - slash: 3.0.0 - - '@jest/transform@30.3.0': - dependencies: - '@babel/core': 7.29.0 - '@jest/types': 30.3.0 - '@jridgewell/trace-mapping': 0.3.31 - babel-plugin-istanbul: 7.0.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 30.3.0 - jest-regex-util: 30.0.1 - jest-util: 30.3.0 - pirates: 4.0.7 - slash: 3.0.0 - write-file-atomic: 5.0.1 - transitivePeerDependencies: - - supports-color - - '@jest/types@30.3.0': - dependencies: - '@jest/pattern': 30.0.1 - '@jest/schemas': 30.0.5 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 22.19.15 - '@types/yargs': 17.0.35 - chalk: 4.1.2 - - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/sourcemap-codec@1.5.5': {} - - '@jridgewell/trace-mapping@0.3.31': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@jridgewell/trace-mapping@0.3.9': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@jsdevtools/ono@7.1.3': {} - - '@json2csv/formatters@7.0.6': {} - - '@json2csv/node@7.0.6': - dependencies: - '@json2csv/plainjs': 7.0.6 - - '@json2csv/plainjs@7.0.6': - dependencies: - '@json2csv/formatters': 7.0.6 - '@streamparser/json': 0.0.20 - - '@napi-rs/wasm-runtime@0.2.12': - dependencies: - '@emnapi/core': 1.9.1 - '@emnapi/runtime': 1.9.1 - '@tybys/wasm-util': 0.10.1 - optional: true - - '@noble/hashes@1.8.0': {} - - '@paralleldrive/cuid2@2.3.1': - dependencies: - '@noble/hashes': 1.8.0 - - '@pinojs/redact@0.4.0': {} - - '@pkgjs/parseargs@0.11.0': - optional: true - - '@pkgr/core@0.2.9': {} - - '@prisma/client@6.19.2(prisma@6.19.2(typescript@5.9.3))(typescript@5.9.3)': - optionalDependencies: - prisma: 6.19.2(typescript@5.9.3) - typescript: 5.9.3 - - '@prisma/config@6.19.2': - dependencies: - c12: 3.1.0 - deepmerge-ts: 7.1.5 - effect: 3.18.4 - empathic: 2.0.0 - transitivePeerDependencies: - - magicast - - '@prisma/debug@6.19.2': {} - - '@prisma/engines-version@7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7': {} - - '@prisma/engines@6.19.2': - dependencies: - '@prisma/debug': 6.19.2 - '@prisma/engines-version': 7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7 - '@prisma/fetch-engine': 6.19.2 - '@prisma/get-platform': 6.19.2 - - '@prisma/fetch-engine@6.19.2': - dependencies: - '@prisma/debug': 6.19.2 - '@prisma/engines-version': 7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7 - '@prisma/get-platform': 6.19.2 - - '@prisma/get-platform@6.19.2': - dependencies: - '@prisma/debug': 6.19.2 - - '@puppeteer/browsers@2.13.0': - dependencies: - debug: 4.4.3(supports-color@5.5.0) - 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 - - '@scarf/scarf@1.4.0': {} - - '@sinclair/typebox@0.34.49': {} - - '@sinonjs/commons@3.0.1': - dependencies: - type-detect: 4.0.8 - - '@sinonjs/fake-timers@15.1.1': - dependencies: - '@sinonjs/commons': 3.0.1 - - '@stablelib/base64@1.0.1': {} - - '@standard-schema/spec@1.1.0': {} - - '@streamparser/json@0.0.20': {} - - '@swc/helpers@0.5.19': - dependencies: - tslib: 2.8.1 - - '@tootallnate/quickjs-emscripten@0.23.0': {} - - '@tsconfig/node10@1.0.12': {} - - '@tsconfig/node12@1.0.11': {} - - '@tsconfig/node14@1.0.3': {} + '@apidevtools/openapi-schemas@2.1.0': {} - '@tsconfig/node16@1.0.4': {} + '@apidevtools/swagger-methods@3.0.2': {} - '@tybys/wasm-util@0.10.1': - dependencies: - tslib: 2.8.1 - optional: true + '@apidevtools/swagger-parser@12.1.0(openapi-types@12.1.3)': + dependencies: + '@apidevtools/json-schema-ref-parser': 14.0.1 + '@apidevtools/openapi-schemas': 2.1.0 + '@apidevtools/swagger-methods': 3.0.2 + ajv: 8.20.0 + ajv-draft-04: 1.0.0(ajv@8.20.0) + call-me-maybe: 1.0.2 + openapi-types: 12.1.3 - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - '@types/babel__generator': 7.27.0 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.28.0 + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 - '@types/babel__generator@7.27.0': - dependencies: - '@babel/types': 7.29.0 + '@babel/compat-data@7.29.7': {} - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@5.5.0) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color - '@types/babel__traverse@7.28.0': - dependencies: - '@babel/types': 7.29.0 + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 - '@types/bcrypt@6.0.0': - dependencies: - '@types/node': 22.19.15 + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.8 + lru-cache: 5.1.1 + semver: 6.3.1 - '@types/body-parser@1.19.6': - dependencies: - '@types/connect': 3.4.38 - '@types/node': 22.19.15 + '@babel/helper-globals@7.29.7': {} - '@types/connect@3.4.38': - dependencies: - '@types/node': 22.19.15 + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color - '@types/cookiejar@2.1.5': {} + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color - '@types/cors@2.8.19': - dependencies: - '@types/node': 22.19.15 + '@babel/helper-plugin-utils@7.29.7': {} - '@types/dotenv@8.2.3': - dependencies: - dotenv: 16.6.1 + '@babel/helper-string-parser@7.29.7': {} - '@types/estree@1.0.8': {} + '@babel/helper-validator-identifier@7.29.7': {} - '@types/express-serve-static-core@5.1.1': - dependencies: - '@types/node': 22.19.15 - '@types/qs': 6.15.0 - '@types/range-parser': 1.2.7 - '@types/send': 1.2.1 + '@babel/helper-validator-option@7.29.7': {} - '@types/express@5.0.6': - dependencies: - '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 5.1.1 - '@types/serve-static': 2.2.0 + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 - '@types/helmet@4.0.0': - dependencies: - helmet: 8.1.0 + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 - '@types/http-errors@2.0.5': {} + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@types/http-proxy@1.17.17': - dependencies: - '@types/node': 22.19.15 + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@types/istanbul-lib-coverage@2.0.6': {} + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@types/istanbul-lib-report@3.0.3': - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@types/istanbul-reports@3.0.4': - dependencies: - '@types/istanbul-lib-report': 3.0.3 + '@babel/plugin-syntax-import-attributes@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@types/jest@30.0.0': - dependencies: - expect: 30.3.0 - pretty-format: 30.3.0 + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@types/js-yaml@4.0.9': {} + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@types/json-schema@7.0.15': {} + '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@types/jsonwebtoken@9.0.10': - dependencies: - '@types/ms': 2.1.0 - '@types/node': 22.19.15 + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@types/methods@1.1.4': {} + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@types/morgan@1.9.10': - dependencies: - '@types/node': 22.19.15 - - '@types/ms@2.1.0': {} - - '@types/multer@1.4.13': - dependencies: - '@types/express': 5.0.6 - - '@types/node@18.19.130': - dependencies: - undici-types: 5.26.5 - - '@types/node@22.19.15': - dependencies: - undici-types: 6.21.0 - - '@types/nodemailer@6.4.23': - dependencies: - '@types/node': 22.19.15 - - '@types/opentype.js@1.3.9': {} - - '@types/pdfkit@0.17.5': - dependencies: - '@types/node': 22.19.15 - - '@types/puppeteer@5.4.7': - dependencies: - '@types/node': 22.19.15 - - '@types/qs@6.15.0': {} - - '@types/range-parser@1.2.7': {} - - '@types/send@1.2.1': - dependencies: - '@types/node': 22.19.15 - - '@types/serve-static@2.2.0': - dependencies: - '@types/http-errors': 2.0.5 - '@types/node': 22.19.15 - - '@types/stack-utils@2.0.3': {} - - '@types/superagent@8.1.10': - dependencies: - '@types/cookiejar': 2.1.5 - '@types/methods': 1.1.4 - '@types/node': 22.19.15 - form-data: 4.0.5 - - '@types/supertest@7.2.0': - dependencies: - '@types/methods': 1.1.4 - '@types/superagent': 8.1.10 - - '@types/swagger-jsdoc@6.0.4': {} - - '@types/swagger-ui-express@4.1.8': - dependencies: - '@types/express': 5.0.6 - '@types/serve-static': 2.2.0 - - '@types/text-to-svg@3.1.4': - dependencies: - '@types/opentype.js': 1.3.9 - - '@types/xlsx@0.0.35': {} - - '@types/yargs-parser@21.0.3': {} - - '@types/yargs@17.0.35': - dependencies: - '@types/yargs-parser': 21.0.3 - - '@types/yauzl@2.10.3': - dependencies: - '@types/node': 22.19.15 - optional: true - - '@typescript-eslint/eslint-plugin@8.57.1(@typescript-eslint/parser@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.57.1 - '@typescript-eslint/type-utils': 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.57.1 - eslint: 9.39.4(jiti@2.6.1) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.57.1 - '@typescript-eslint/types': 8.57.1 - '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.57.1 - debug: 4.4.3(supports-color@5.5.0) - eslint: 9.39.4(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/project-service@8.57.1(typescript@5.9.3)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.57.1(typescript@5.9.3) - '@typescript-eslint/types': 8.57.1 - debug: 4.4.3(supports-color@5.5.0) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@8.57.1': - dependencies: - '@typescript-eslint/types': 8.57.1 - '@typescript-eslint/visitor-keys': 8.57.1 - - '@typescript-eslint/tsconfig-utils@8.57.1(typescript@5.9.3)': - dependencies: - typescript: 5.9.3 - - '@typescript-eslint/type-utils@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/types': 8.57.1 - '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - debug: 4.4.3(supports-color@5.5.0) - eslint: 9.39.4(jiti@2.6.1) - ts-api-utils: 2.5.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.57.1': {} - - '@typescript-eslint/typescript-estree@8.57.1(typescript@5.9.3)': - dependencies: - '@typescript-eslint/project-service': 8.57.1(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.57.1(typescript@5.9.3) - '@typescript-eslint/types': 8.57.1 - '@typescript-eslint/visitor-keys': 8.57.1 - debug: 4.4.3(supports-color@5.5.0) - minimatch: 10.2.4 - semver: 7.7.4 - tinyglobby: 0.2.15 - ts-api-utils: 2.5.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.57.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.57.1 - '@typescript-eslint/types': 8.57.1 - '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) - eslint: 9.39.4(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.57.1': - dependencies: - '@typescript-eslint/types': 8.57.1 - eslint-visitor-keys: 5.0.1 - - '@ungap/structured-clone@1.3.0': {} - - '@unrs/resolver-binding-android-arm-eabi@1.11.1': - optional: true - - '@unrs/resolver-binding-android-arm64@1.11.1': - optional: true - - '@unrs/resolver-binding-darwin-arm64@1.11.1': - optional: true - - '@unrs/resolver-binding-darwin-x64@1.11.1': - optional: true - - '@unrs/resolver-binding-freebsd-x64@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm64-musl@1.11.1': - optional: true + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': - optional: true + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': - optional: true + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': - optional: true + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': - optional: true + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@unrs/resolver-binding-linux-x64-gnu@1.11.1': - optional: true + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@unrs/resolver-binding-linux-x64-musl@1.11.1': - optional: true + '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@unrs/resolver-binding-wasm32-wasi@1.11.1': - dependencies: - '@napi-rs/wasm-runtime': 0.2.12 - optional: true + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 - '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': - optional: true + '@babel/traverse@7.29.8': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + debug: 4.4.3(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color - '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': - optional: true + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 - '@unrs/resolver-binding-win32-x64-msvc@1.11.1': - optional: true + '@bcoe/v8-coverage@0.2.3': {} - accepts@2.0.0: - dependencies: - mime-types: 3.0.2 - negotiator: 1.0.0 + '@cloudflare/json-schema-walker@0.1.1': {} - acorn-jsx@5.3.2(acorn@8.16.0): - dependencies: - acorn: 8.16.0 + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 - acorn-walk@8.3.5: - dependencies: - acorn: 8.16.0 + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true - acorn@8.16.0: {} + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true - adler-32@1.3.1: {} + '@emnapi/runtime@1.11.3': + dependencies: + tslib: 2.8.1 + optional: true - agent-base@7.1.4: {} + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true - ajv@6.14.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 + '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(jiti@2.7.0))': + dependencies: + eslint: 9.39.5(jiti@2.7.0) + eslint-visitor-keys: 3.4.3 - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 + '@eslint-community/regexpp@4.12.2': {} - ansi-escapes@7.3.0: - dependencies: - environment: 1.1.0 + '@eslint/config-array@0.21.2': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3(supports-color@5.5.0) + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color - ansi-regex@5.0.1: {} + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 - ansi-regex@6.2.2: {} + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 + '@eslint/eslintrc@3.3.6': + dependencies: + ajv: 6.15.0 + debug: 4.4.3(supports-color@5.5.0) + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.3.1 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color - ansi-styles@5.2.0: {} + '@eslint/js@9.39.5': {} - ansi-styles@6.2.3: {} + '@eslint/object-schema@2.1.7': {} - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 - append-field@1.0.0: {} + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 - arg@4.1.3: {} + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 - argparse@1.0.10: - dependencies: - sprintf-js: 1.0.3 + '@humanfs/types@0.15.0': {} - argparse@2.0.1: {} - - asap@2.0.6: {} - - ast-types@0.13.4: - dependencies: - tslib: 2.8.1 + '@humanwhocodes/module-importer@1.0.1': {} - asynckit@0.4.0: {} + '@humanwhocodes/retry@0.4.3': {} - atomic-sleep@1.0.0: {} + '@img/colour@1.1.0': {} - b4a@1.8.0: {} + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true - babel-jest@30.3.0(@babel/core@7.29.0): - dependencies: - '@babel/core': 7.29.0 - '@jest/transform': 30.3.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 7.0.1 - babel-preset-jest: 30.3.0(@babel/core@7.29.0) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true - babel-plugin-istanbul@7.0.1: - dependencies: - '@babel/helper-plugin-utils': 7.28.6 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 6.0.3 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-jest-hoist@30.3.0: - dependencies: - '@types/babel__core': 7.20.5 - - babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.0): - dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.0) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.0) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.0) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.0) - '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.0) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.0) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.0) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.0) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.0) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.0) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.0) - - babel-preset-jest@30.3.0(@babel/core@7.29.0): - dependencies: - '@babel/core': 7.29.0 - babel-plugin-jest-hoist: 30.3.0 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) - - balanced-match@1.0.2: {} - - balanced-match@4.0.4: {} - - bare-events@2.8.2: {} - - bare-fs@4.5.6: - dependencies: - bare-events: 2.8.2 - bare-path: 3.0.0 - bare-stream: 2.10.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.0: {} - - bare-path@3.0.0: - dependencies: - bare-os: 3.8.0 - - bare-stream@2.10.0(bare-events@2.8.2): - dependencies: - streamx: 2.25.0 - teex: 1.0.1 - optionalDependencies: - bare-events: 2.8.2 - transitivePeerDependencies: - - bare-abort-controller - - react-native-b4a - - bare-url@2.4.0: - dependencies: - bare-path: 3.0.0 - - base64-js@0.0.8: {} - - base64-js@1.5.1: {} - - baseline-browser-mapping@2.10.12: {} - - basic-auth@2.0.1: - dependencies: - safe-buffer: 5.1.2 - - basic-ftp@5.2.0: {} - - bcrypt@6.0.0: - dependencies: - node-addon-api: 8.6.0 - node-gyp-build: 4.8.4 - - bignumber.js@9.3.1: {} - - binary-extensions@2.3.0: {} - - body-parser@2.2.2: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 4.4.3(supports-color@5.5.0) - http-errors: 2.0.1 - iconv-lite: 0.7.2 - on-finished: 2.4.1 - qs: 6.15.0 - raw-body: 3.0.2 - type-is: 2.0.1 - transitivePeerDependencies: - - supports-color - - brace-expansion@1.1.12: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.2: - dependencies: - balanced-match: 1.0.2 - - brace-expansion@5.0.4: - dependencies: - balanced-match: 4.0.4 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - brotli@1.3.3: - dependencies: - base64-js: 1.5.1 - - browserslist@4.28.1: - dependencies: - baseline-browser-mapping: 2.10.12 - caniuse-lite: 1.0.30001782 - electron-to-chromium: 1.5.329 - node-releases: 2.0.36 - update-browserslist-db: 1.2.3(browserslist@4.28.1) - - bs-logger@0.2.6: - dependencies: - fast-json-stable-stringify: 2.1.0 - - bser@2.1.1: - dependencies: - node-int64: 0.4.0 - - buffer-crc32@0.2.13: {} - - buffer-equal-constant-time@1.0.1: {} - - buffer-from@1.1.2: {} - - busboy@1.6.0: - dependencies: - streamsearch: 1.1.0 - - bytes@3.1.2: {} - - c12@3.1.0: - dependencies: - chokidar: 4.0.3 - confbox: 0.2.4 - defu: 6.1.4 - dotenv: 16.6.1 - exsolve: 1.0.8 - giget: 2.0.0 - jiti: 2.6.1 - ohash: 2.0.11 - pathe: 2.0.3 - perfect-debounce: 1.0.0 - pkg-types: 2.3.0 - rc9: 2.1.2 + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true - call-me-maybe@1.0.2: {} + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true - callsites@3.1.0: {} + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true - camelcase@5.3.1: {} + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true - camelcase@6.3.0: {} + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true - caniuse-lite@1.0.30001782: {} + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true - cfb@1.2.2: - dependencies: - adler-32: 1.3.1 - crc-32: 1.2.2 + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true - chalk@5.6.2: {} + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true - char-regex@1.0.2: {} + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true - chokidar@4.0.3: - dependencies: - readdirp: 4.1.2 + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true - chromium-bidi@14.0.0(devtools-protocol@0.0.1581282): - dependencies: - devtools-protocol: 0.0.1581282 - mitt: 3.0.1 - zod: 3.25.76 + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true - ci-info@4.4.0: {} + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true - citty@0.1.6: - dependencies: - consola: 3.4.2 + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true - citty@0.2.1: {} + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true - cjs-module-lexer@2.2.0: {} + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.11.3 + optional: true - cli-cursor@5.0.0: - dependencies: - restore-cursor: 5.1.0 + '@img/sharp-win32-arm64@0.34.5': + optional: true - cli-truncate@4.0.0: - dependencies: - slice-ansi: 5.0.0 - string-width: 7.2.0 + '@img/sharp-win32-ia32@0.34.5': + optional: true - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 + '@img/sharp-win32-x64@0.34.5': + optional: true - clone@2.1.2: {} + '@ioredis/commands@2.0.0': {} - cloudinary@2.9.0: - dependencies: - lodash: 4.17.23 + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 - cluster-key-slot@1.1.1: {} + '@isaacs/cliui@9.0.0': {} - co@4.6.0: {} + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.15.1 + resolve-from: 5.0.0 - codepage@1.15.0: {} + '@istanbuljs/schema@0.1.6': {} - collect-v8-coverage@1.0.3: {} + '@jest/console@30.4.1': + dependencies: + '@jest/types': 30.4.1 + '@types/node': 22.20.1 + chalk: 4.1.2 + jest-message-util: 30.4.1 + jest-util: 30.4.1 + slash: 3.0.0 - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 + '@jest/core@30.4.2(ts-node@10.9.2(@types/node@22.20.1)(typescript@5.9.3))': + dependencies: + '@jest/console': 30.4.1 + '@jest/pattern': 30.4.0 + '@jest/reporters': 30.4.1 + '@jest/test-result': 30.4.1 + '@jest/transform': 30.4.1 + '@jest/types': 30.4.1 + '@types/node': 22.20.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 4.4.0 + exit-x: 0.2.2 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-changed-files: 30.4.1 + jest-config: 30.4.2(@types/node@22.20.1)(ts-node@10.9.2(@types/node@22.20.1)(typescript@5.9.3)) + jest-haste-map: 30.4.1 + jest-message-util: 30.4.1 + jest-regex-util: 30.4.0 + jest-resolve: 30.4.1 + jest-resolve-dependencies: 30.4.2 + jest-runner: 30.4.2 + jest-runtime: 30.4.2 + jest-snapshot: 30.4.1 + jest-util: 30.4.1 + jest-validate: 30.4.1 + jest-watcher: 30.4.1 + pretty-format: 30.4.1 + slash: 3.0.0 + transitivePeerDependencies: + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + '@jest/diff-sequences@30.4.0': {} + + '@jest/environment@30.4.1': + dependencies: + '@jest/fake-timers': 30.4.1 + '@jest/types': 30.4.1 + '@types/node': 22.20.1 + jest-mock: 30.4.1 + + '@jest/expect-utils@30.4.1': + dependencies: + '@jest/get-type': 30.1.0 + + '@jest/expect@30.4.1': + dependencies: + expect: 30.4.1 + jest-snapshot: 30.4.1 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@30.4.1': + dependencies: + '@jest/types': 30.4.1 + '@sinonjs/fake-timers': 15.4.0 + '@types/node': 22.20.1 + jest-message-util: 30.4.1 + jest-mock: 30.4.1 + jest-util: 30.4.1 + + '@jest/get-type@30.1.0': {} + + '@jest/globals@30.4.1': + dependencies: + '@jest/environment': 30.4.1 + '@jest/expect': 30.4.1 + '@jest/types': 30.4.1 + jest-mock: 30.4.1 + transitivePeerDependencies: + - supports-color + + '@jest/pattern@30.4.0': + dependencies: + '@types/node': 22.20.1 + jest-regex-util: 30.4.0 + + '@jest/reporters@30.4.1': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 30.4.1 + '@jest/test-result': 30.4.1 + '@jest/transform': 30.4.1 + '@jest/types': 30.4.1 + '@jridgewell/trace-mapping': 0.3.31 + '@types/node': 22.20.1 + chalk: 4.1.2 + collect-v8-coverage: 1.0.3 + exit-x: 0.2.2 + glob: 10.5.0 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + jest-message-util: 30.4.1 + jest-util: 30.4.1 + jest-worker: 30.4.1 + slash: 3.0.0 + string-length: 4.0.2 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@30.4.1': + dependencies: + '@sinclair/typebox': 0.34.52 + + '@jest/snapshot-utils@30.4.1': + dependencies: + '@jest/types': 30.4.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + natural-compare: 1.4.0 + + '@jest/source-map@30.0.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@30.4.1': + dependencies: + '@jest/console': 30.4.1 + '@jest/types': 30.4.1 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.3 + + '@jest/test-sequencer@30.4.1': + dependencies: + '@jest/test-result': 30.4.1 + graceful-fs: 4.2.11 + jest-haste-map: 30.4.1 + slash: 3.0.0 + + '@jest/transform@30.4.1': + dependencies: + '@babel/core': 7.29.7 + '@jest/types': 30.4.1 + '@jridgewell/trace-mapping': 0.3.31 + babel-plugin-istanbul: 7.0.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.4.1 + jest-regex-util: 30.4.0 + jest-util: 30.4.1 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + + '@jest/types@30.4.1': + dependencies: + '@jest/pattern': 30.4.0 + '@jest/schemas': 30.4.1 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.20.1 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@json2csv/formatters@7.0.8': {} + + '@json2csv/node@7.0.8': + dependencies: + '@json2csv/plainjs': 7.0.8 + + '@json2csv/plainjs@7.0.8': + dependencies: + '@json2csv/formatters': 7.0.8 + '@streamparser/json': 0.0.23 + + '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@noble/curves@1.9.7': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/hashes@1.8.0': {} + + '@paralleldrive/cuid2@2.3.1': + dependencies: + '@noble/hashes': 1.8.0 + + '@pinojs/redact@0.4.0': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.3.6': {} + + '@prisma/client@6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3)': + optionalDependencies: + prisma: 6.19.3(typescript@5.9.3) + typescript: 5.9.3 + + '@prisma/config@6.19.3': + dependencies: + c12: 3.1.0 + deepmerge-ts: 7.1.5 + effect: 3.21.0 + empathic: 2.0.0 + transitivePeerDependencies: + - magicast + + '@prisma/debug@6.19.3': {} + + '@prisma/engines-version@7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7': + {} + + '@prisma/engines@6.19.3': + dependencies: + '@prisma/debug': 6.19.3 + '@prisma/engines-version': 7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7 + '@prisma/fetch-engine': 6.19.3 + '@prisma/get-platform': 6.19.3 + + '@prisma/fetch-engine@6.19.3': + dependencies: + '@prisma/debug': 6.19.3 + '@prisma/engines-version': 7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7 + '@prisma/get-platform': 6.19.3 + + '@prisma/get-platform@6.19.3': + dependencies: + '@prisma/debug': 6.19.3 + + '@puppeteer/browsers@2.13.2': + dependencies: + debug: 4.4.3(supports-color@5.5.0) + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.5.0 + semver: 7.8.5 + tar-fs: 3.1.3 + yargs: 17.7.3 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + - supports-color + + '@scarf/scarf@1.4.0': {} + + '@sinclair/typebox@0.34.52': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@15.4.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@stablelib/base64@1.0.1': {} + + '@standard-schema/spec@1.1.0': {} + + '@stellar/js-xdr@4.0.0': {} + + '@stellar/stellar-base@15.0.0': + dependencies: + '@noble/curves': 1.9.7 + '@stellar/js-xdr': 4.0.0 + base32.js: 0.1.0 + bignumber.js: 9.3.1 + buffer: 6.0.3 + sha.js: 2.4.12 + + '@streamparser/json@0.0.23': {} + + '@swc/helpers@0.5.23': + dependencies: + tslib: 2.8.1 + + '@tootallnate/quickjs-emscripten@0.23.0': {} + + '@tsconfig/node10@1.0.13': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.8 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.8 + + '@types/bcrypt@6.0.0': + dependencies: + '@types/node': 22.20.1 + + '@types/body-parser@1.19.6': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.20.1 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 22.20.1 + + '@types/cookiejar@2.1.5': {} + + '@types/cors@2.8.19': + dependencies: + '@types/node': 22.20.1 + + '@types/dotenv@8.2.3': + dependencies: + dotenv: 16.6.1 + + '@types/estree@1.0.9': {} + + '@types/express-serve-static-core@5.1.3': + dependencies: + '@types/node': 22.20.1 + '@types/qs': 6.15.1 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 + + '@types/express@5.0.6': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 5.1.3 + '@types/serve-static': 2.2.0 + + '@types/helmet@4.0.0': + dependencies: + helmet: 8.3.0 + + '@types/http-errors@2.0.5': {} + + '@types/http-proxy@1.17.17': + dependencies: + '@types/node': 22.20.1 + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@30.0.0': + dependencies: + expect: 30.4.1 + pretty-format: 30.4.1 + + '@types/js-yaml@4.0.9': {} + + '@types/json-schema@7.0.15': {} + + '@types/jsonwebtoken@9.0.10': + dependencies: + '@types/ms': 2.1.0 + '@types/node': 22.20.1 + + '@types/methods@1.1.4': {} + + '@types/morgan@1.9.10': + dependencies: + '@types/node': 22.20.1 + + '@types/ms@2.1.0': {} + + '@types/multer@1.4.13': + dependencies: + '@types/express': 5.0.6 + + '@types/node@18.19.130': + dependencies: + undici-types: 5.26.5 + + '@types/node@22.20.1': + dependencies: + undici-types: 6.21.0 + + '@types/nodemailer@6.4.24': + dependencies: + '@types/node': 22.20.1 + + '@types/opentype.js@1.3.10': {} + + '@types/pdfkit@0.17.6': + dependencies: + '@types/node': 22.20.1 + + '@types/puppeteer@5.4.7': + dependencies: + '@types/node': 22.20.1 + + '@types/qs@6.15.1': {} + + '@types/range-parser@1.2.7': {} + + '@types/send@1.2.1': + dependencies: + '@types/node': 22.20.1 + + '@types/serve-static@2.2.0': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 22.20.1 + + '@types/stack-utils@2.0.3': {} + + '@types/superagent@8.1.11': + dependencies: + '@types/cookiejar': 2.1.5 + '@types/methods': 1.1.4 + '@types/node': 22.20.1 + form-data: 4.0.6 + + '@types/supertest@7.2.1': + dependencies: + '@types/methods': 1.1.4 + '@types/superagent': 8.1.11 + + '@types/swagger-jsdoc@6.0.4': {} + + '@types/swagger-ui-express@4.1.8': + dependencies: + '@types/express': 5.0.6 + '@types/serve-static': 2.2.0 + + '@types/text-to-svg@3.1.4': + dependencies: + '@types/opentype.js': 1.3.10 + + '@types/xlsx@0.0.35': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 22.20.1 + optional: true + + '@typescript-eslint/eslint-plugin@8.68.0(@typescript-eslint/parser@8.68.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.68.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.68.0 + '@typescript-eslint/type-utils': 8.68.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/utils': 8.68.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.68.0 + eslint: 9.39.5(jiti@2.7.0) + ignore: 7.0.6 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.68.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.68.0 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/typescript-estree': 8.68.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.68.0 + debug: 4.4.3(supports-color@5.5.0) + eslint: 9.39.5(jiti@2.7.0) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.68.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.68.0(typescript@5.9.3) + '@typescript-eslint/types': 8.68.0 + debug: 4.4.3(supports-color@5.5.0) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.68.0': + dependencies: + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/visitor-keys': 8.68.0 + + '@typescript-eslint/tsconfig-utils@8.68.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.68.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/typescript-estree': 8.68.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.68.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + debug: 4.4.3(supports-color@5.5.0) + eslint: 9.39.5(jiti@2.7.0) + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.68.0': {} + + '@typescript-eslint/typescript-estree@8.68.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.68.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.68.0(typescript@5.9.3) + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/visitor-keys': 8.68.0 + debug: 4.4.3(supports-color@5.5.0) + minimatch: 10.2.6 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.68.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.68.0 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/typescript-estree': 8.68.0(typescript@5.9.3) + eslint: 9.39.5(jiti@2.7.0) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.68.0': + dependencies: + '@typescript-eslint/types': 8.68.0 + eslint-visitor-keys: 5.0.1 + + '@ungap/structured-clone@1.3.4': {} + + '@unrs/resolver-binding-android-arm-eabi@1.12.2': + optional: true + + '@unrs/resolver-binding-android-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.12.2': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-loong64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-openharmony-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.12.2': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.12.2': + optional: true + + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.1.0 + + acorn-jsx@5.3.2(acorn@8.18.0): + dependencies: + acorn: 8.18.0 + + acorn-walk@8.3.5: + dependencies: + acorn: 8.18.0 + + acorn@8.18.0: {} + + adler-32@1.3.1: {} + + agent-base@7.1.4: {} + + ajv-draft-04@1.0.0(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-escapes@7.3.0: + dependencies: + environment: 1.1.0 + + ansi-regex@5.0.1: {} + + ansi-regex@6.3.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.3: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + append-field@1.0.0: {} + + arg@4.1.3: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 - color-name@1.1.4: {} + argparse@2.0.1: {} - colorette@2.0.20: {} + asap@2.0.6: {} - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + + asynckit@0.4.0: {} + + atomic-sleep@1.0.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + b4a@1.8.1: {} + + babel-jest@30.4.1(@babel/core@7.29.7): + dependencies: + '@babel/core': 7.29.7 + '@jest/transform': 30.4.1 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 7.0.1 + babel-preset-jest: 30.4.0(@babel/core@7.29.7) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@7.0.1: + dependencies: + '@babel/helper-plugin-utils': 7.29.7 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-instrument: 6.0.3 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@30.4.0: + dependencies: + '@types/babel__core': 7.20.5 + + babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.7): + dependencies: + '@babel/core': 7.29.7 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.7) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.7) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.7) + '@babel/plugin-syntax-import-attributes': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.7) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.7) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.7) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.7) + + babel-preset-jest@30.4.0(@babel/core@7.29.7): + dependencies: + '@babel/core': 7.29.7 + babel-plugin-jest-hoist: 30.4.0 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7) + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + bare-events@2.9.2: {} + + bare-fs@4.8.1: + dependencies: + bare-events: 2.9.2 + bare-path: 3.1.1 + bare-stream: 2.13.4(bare-events@2.9.2) + bare-url: 2.5.2 + fast-fifo: 1.3.2 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + bare-path@3.1.1: {} + + bare-stream@2.13.4(bare-events@2.9.2): + dependencies: + b4a: 1.8.1 + streamx: 2.28.1 + teex: 1.0.1 + optionalDependencies: + bare-events: 2.9.2 + transitivePeerDependencies: + - react-native-b4a + + bare-url@2.5.2: + dependencies: + bare-path: 3.1.1 + + base32.js@0.1.0: {} + + base64-js@0.0.8: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.11.19: {} + + basic-auth@2.0.1: + dependencies: + safe-buffer: 5.1.2 + + basic-ftp@5.3.1: {} + + bcrypt@6.0.0: + dependencies: + node-addon-api: 8.9.2 + node-gyp-build: 4.8.4 + + bignumber.js@9.3.1: {} + + binary-extensions@2.3.0: {} + + body-parser@2.3.0: + dependencies: + bytes: 3.1.2 + content-type: 2.1.0 + debug: 4.4.3(supports-color@5.5.0) + http-errors: 2.0.1 + iconv-lite: 0.7.3 + on-finished: 2.4.1 + qs: 6.15.3 + raw-body: 3.0.2 + type-is: 2.1.0 + transitivePeerDependencies: + - supports-color + + brace-expansion@1.1.18: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.1.4: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.9: + dependencies: + balanced-match: 4.0.4 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + brotli@1.3.3: + dependencies: + base64-js: 1.5.1 + + browserify-zlib@0.2.0: + dependencies: + pako: 1.0.11 + + browserslist@4.28.8: + dependencies: + baseline-browser-mapping: 2.11.19 + caniuse-lite: 1.0.30001810 + electron-to-chromium: 1.5.415 + node-releases: 2.0.53 + update-browserslist-db: 1.3.1(browserslist@4.28.8) + + bs-logger@0.2.6: + dependencies: + fast-json-stable-stringify: 2.1.0 + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-crc32@0.2.13: {} + + buffer-equal-constant-time@1.0.1: {} + + buffer-from@1.1.2: {} + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + + bytes@3.1.2: {} + + c12@3.1.0: + dependencies: + chokidar: 4.0.3 + confbox: 0.2.4 + defu: 6.1.7 + dotenv: 16.6.1 + exsolve: 1.1.1 + giget: 2.0.0 + jiti: 2.7.0 + ohash: 2.0.12 + pathe: 2.0.3 + perfect-debounce: 1.0.0 + pkg-types: 2.3.1 + rc9: 2.1.2 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 - commander@13.1.0: {} + call-bind@1.0.9: + 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 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + call-me-maybe@1.0.2: {} + + callsites@3.1.0: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001810: {} + + cfb@1.2.2: + dependencies: + adler-32: 1.3.1 + crc-32: 1.2.2 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + char-regex@1.0.2: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chromium-bidi@14.0.0(devtools-protocol@0.0.1608973): + dependencies: + devtools-protocol: 0.0.1608973 + mitt: 3.0.1 + zod: 3.25.76 + + ci-info@4.4.0: {} + + citty@0.1.6: + dependencies: + consola: 3.4.2 + + citty@0.2.2: {} + + cjs-module-lexer@2.2.1: {} + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@2.1.2: {} - commander@2.20.3: {} + cloudinary@2.10.1: + dependencies: + lodash: 4.18.1 - commander@6.2.0: {} + cluster-key-slot@1.1.1: {} - commander@9.5.0: - optional: true + co@4.6.0: {} - component-emitter@1.3.1: {} + codepage@1.15.0: {} - concat-map@0.0.1: {} + collect-v8-coverage@1.0.3: {} - concat-stream@1.6.2: - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 2.3.8 - typedarray: 0.0.6 + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 - confbox@0.2.4: {} + color-name@1.1.4: {} - consola@3.4.2: {} + colorette@2.0.20: {} - content-disposition@1.0.1: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 - content-type@1.0.5: {} + commander@13.1.0: {} - convert-source-map@2.0.0: {} + commander@2.20.3: {} - cookie-signature@1.2.2: {} + commander@6.2.0: {} - cookie@0.7.2: {} + component-emitter@1.3.1: {} - cookiejar@2.1.4: {} + concat-map@0.0.1: {} - core-util-is@1.0.3: {} + concat-stream@1.6.2: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.8 + typedarray: 0.0.6 - cors@2.8.6: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 + confbox@0.2.4: {} - cosmiconfig@9.0.1(typescript@5.9.3): - dependencies: - env-paths: 2.2.1 - import-fresh: 3.3.1 - js-yaml: 4.1.1 - parse-json: 5.2.0 - optionalDependencies: - typescript: 5.9.3 + consola@3.4.2: {} - crc-32@1.2.2: {} + content-disposition@1.1.0: {} - create-require@1.1.1: {} + content-type@1.0.5: {} - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 + content-type@2.1.0: {} - crypto-js@4.2.0: {} + convert-source-map@2.0.0: {} - data-uri-to-buffer@4.0.1: {} + cookie-signature@1.2.2: {} - data-uri-to-buffer@6.0.2: {} + cookie@0.7.2: {} - debug@2.6.9: - dependencies: - ms: 2.0.0 + cookiejar@2.1.4: {} - debug@4.4.3(supports-color@5.5.0): - dependencies: - ms: 2.1.3 - optionalDependencies: - supports-color: 5.5.0 + core-util-is@1.0.3: {} - dedent@1.7.2: {} + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 - deep-is@0.1.4: {} + cosmiconfig@9.0.2(typescript@5.9.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.3.1 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.9.3 - deepmerge-ts@7.1.5: {} + crc-32@1.2.2: {} - deepmerge@4.3.1: {} + create-require@1.1.1: {} - defu@6.1.4: {} + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 - degenerator@5.0.1: - dependencies: - ast-types: 0.13.4 - escodegen: 2.1.0 - esprima: 4.0.1 + crypto-js@4.2.0: {} - delayed-stream@1.0.0: {} + data-uri-to-buffer@4.0.1: {} - denque@2.1.0: {} + data-uri-to-buffer@6.0.2: {} dateformat@4.6.3: {} @@ -7985,615 +7983,138 @@ snapshots: dependencies: ms: 2.0.0 - destr@2.0.5: {} + debug@4.4.3(supports-color@5.5.0): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 5.5.0 + + dedent@1.7.2: {} + + deep-is@0.1.4: {} + + deepmerge-ts@7.1.5: {} + + deepmerge@4.3.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + defu@6.1.7: {} + + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + + delayed-stream@1.0.0: {} + + denque@2.1.0: {} - detect-libc@2.1.2: {} + depd@2.0.0: {} - detect-newline@3.1.0: {} + destr@2.0.5: {} - devtools-protocol@0.0.1581282: {} + detect-libc@2.1.2: {} - dezalgo@1.0.4: - dependencies: - asap: 2.0.6 - wrappy: 1.0.2 + detect-newline@3.1.0: {} - dfa@1.2.0: {} + devtools-protocol@0.0.1608973: {} - diff@4.0.4: {} + dezalgo@1.0.4: + dependencies: + asap: 2.0.6 + wrappy: 1.0.2 - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 + dfa@1.2.0: {} - dotenv@16.6.1: {} + diff@4.0.4: {} - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 - eastasianwidth@0.2.0: {} + dotenv@16.6.1: {} - ecdsa-sig-formatter@1.0.11: - dependencies: - safe-buffer: 5.2.1 + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 - ee-first@1.1.1: {} + eastasianwidth@0.2.0: {} - effect@3.18.4: - dependencies: - '@standard-schema/spec': 1.1.0 - fast-check: 3.23.2 + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 - electron-to-chromium@1.5.329: {} + ee-first@1.1.1: {} - emittery@0.13.1: {} + effect@3.21.0: + dependencies: + '@standard-schema/spec': 1.1.0 + fast-check: 3.23.2 - emoji-regex@10.6.0: {} + electron-to-chromium@1.5.415: {} - emoji-regex@8.0.0: {} + emittery@0.13.1: {} - emoji-regex@9.2.2: {} + emoji-regex@10.6.0: {} - empathic@2.0.0: {} + emoji-regex@8.0.0: {} - encodeurl@2.0.0: {} + emoji-regex@9.2.2: {} - end-of-stream@1.4.5: - dependencies: - once: 1.4.0 + empathic@2.0.0: {} - env-paths@2.2.1: {} + encodeurl@2.0.0: {} - environment@1.1.0: {} + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 - error-ex@1.3.4: - dependencies: - is-arrayish: 0.2.1 + env-paths@2.2.1: {} - es-define-property@1.0.1: {} + environment@1.1.0: {} - es-errors@1.3.0: {} + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 + es-define-property@1.0.1: {} - 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 + es-errors@1.3.0: {} - escalade@3.2.0: {} + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 - escape-html@1.0.3: {} + 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.4 - escape-string-regexp@2.0.0: {} + escalade@3.2.0: {} - escape-string-regexp@4.0.0: {} + escape-html@1.0.3: {} - escodegen@2.1.0: - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionalDependencies: - source-map: 0.6.1 + escape-string-regexp@2.0.0: {} - eslint-scope@8.4.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.1: {} - - eslint-visitor-keys@5.0.1: {} - - eslint@9.39.4(jiti@2.6.1): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.2 - '@eslint/config-helpers': 0.4.2 - '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.5 - '@eslint/js': 9.39.4 - '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.7 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.14.0 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@5.5.0) - escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.7.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.5 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.6.1 - transitivePeerDependencies: - - supports-color - - espree@10.4.0: - dependencies: - acorn: 8.16.0 - acorn-jsx: 5.3.2(acorn@8.16.0) - eslint-visitor-keys: 4.2.1 - - esprima@4.0.1: {} - - esquery@1.7.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - esutils@2.0.3: {} - - etag@1.8.1: {} - - eventemitter3@4.0.7: {} - - eventemitter3@5.0.4: {} - - events-universal@1.0.1: - dependencies: - bare-events: 2.8.2 - transitivePeerDependencies: - - bare-abort-controller - - execa@5.1.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - execa@8.0.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - - exit-x@0.2.2: {} - - expect@30.3.0: - dependencies: - '@jest/expect-utils': 30.3.0 - '@jest/get-type': 30.1.0 - jest-matcher-utils: 30.3.0 - jest-message-util: 30.3.0 - jest-mock: 30.3.0 - jest-util: 30.3.0 - - express-rate-limit@8.3.1(express@5.2.1): - dependencies: - express: 5.2.1 - ip-address: 10.1.0 - - express@5.2.1: - dependencies: - accepts: 2.0.0 - body-parser: 2.2.2 - content-disposition: 1.0.1 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.2.2 - debug: 4.4.3(supports-color@5.5.0) - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 2.1.1 - fresh: 2.0.0 - http-errors: 2.0.1 - merge-descriptors: 2.0.0 - mime-types: 3.0.2 - on-finished: 2.4.1 - once: 1.4.0 - parseurl: 1.3.3 - proxy-addr: 2.0.7 - qs: 6.15.0 - range-parser: 1.2.1 - router: 2.2.0 - send: 1.2.1 - serve-static: 2.2.1 - statuses: 2.0.2 - type-is: 2.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - - exsolve@1.0.8: {} - - extend@3.0.2: {} - - extract-zip@2.0.1: - dependencies: - debug: 4.4.3(supports-color@5.5.0) - get-stream: 5.2.0 - yauzl: 2.10.0 - optionalDependencies: - '@types/yauzl': 2.10.3 - transitivePeerDependencies: - - supports-color - - fast-check@3.23.2: - dependencies: - pure-rand: 6.1.0 - - fast-deep-equal@3.1.3: {} - - fast-fifo@1.3.2: {} - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fast-safe-stringify@2.1.1: {} - - fast-sha256@1.3.0: {} - - fb-watchman@2.0.2: - dependencies: - bser: 2.1.1 - - fd-slicer@1.1.0: - dependencies: - pend: 1.2.0 - - fdir@6.5.0(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 - - fetch-blob@3.2.0: - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.3.3 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - finalhandler@2.1.1: - dependencies: - debug: 4.4.3(supports-color@5.5.0) - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.4.2 - keyv: 4.5.4 - - flatted@3.4.2: {} - - follow-redirects@1.15.11(debug@4.4.3): - optionalDependencies: - debug: 4.4.3(supports-color@5.5.0) - - fontkit@2.0.4: - dependencies: - '@swc/helpers': 0.5.19 - brotli: 1.3.3 - clone: 2.1.2 - dfa: 1.2.0 - fast-deep-equal: 3.1.3 - restructure: 3.0.2 - tiny-inflate: 1.0.3 - unicode-properties: 1.4.1 - unicode-trie: 2.0.0 - - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - - 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 - - formdata-polyfill@4.0.10: - dependencies: - fetch-blob: 3.2.0 - - formidable@3.5.4: - dependencies: - '@paralleldrive/cuid2': 2.3.1 - dezalgo: 1.0.4 - once: 1.4.0 - - forwarded@0.2.0: {} - - frac@1.1.2: {} - - fresh@2.0.0: {} - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - function-bind@1.1.2: {} - - gaxios@7.1.4: - dependencies: - extend: 3.0.2 - https-proxy-agent: 7.0.6 - node-fetch: 3.3.2 - transitivePeerDependencies: - - supports-color - - gcp-metadata@8.1.2: - dependencies: - gaxios: 7.1.4 - google-logging-utils: 1.1.3 - json-bigint: 1.0.0 - transitivePeerDependencies: - - supports-color - - gensync@1.0.0-beta.2: {} - - get-caller-file@2.0.5: {} - - get-east-asian-width@1.5.0: {} - - 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-package-type@0.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@8.0.1: {} - - get-uri@6.0.5: - dependencies: - basic-ftp: 5.2.0 - data-uri-to-buffer: 6.0.2 - debug: 4.4.3(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - giget@2.0.0: - dependencies: - citty: 0.1.6 - consola: 3.4.2 - defu: 6.1.4 - node-fetch-native: 1.6.7 - nypm: 0.6.5 - pathe: 2.0.3 - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@10.5.0: - dependencies: - foreground-child: 3.3.1 - jackspeak: 3.4.3 - minimatch: 9.0.9 - minipass: 7.1.3 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - - glob@7.1.6: - 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 - - 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 - - glob@8.1.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.9 - once: 1.4.0 - - globals@14.0.0: {} - - google-auth-library@10.6.2: - dependencies: - base64-js: 1.5.1 - ecdsa-sig-formatter: 1.0.11 - gaxios: 7.1.4 - gcp-metadata: 8.1.2 - google-logging-utils: 1.1.3 - jws: 4.0.1 - transitivePeerDependencies: - - supports-color - - google-logging-utils@1.1.3: {} - - gopd@1.2.0: {} - - graceful-fs@4.2.11: {} - - handlebars@4.7.9: - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.19.3 - - has-flag@3.0.0: {} - - has-flag@4.0.0: {} - - 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 - - helmet@8.1.0: {} - - html-escaper@2.0.2: {} - - http-errors@2.0.1: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.2 - toidentifier: 1.0.1 - - http-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - http-proxy-middleware@2.0.9(@types/express@5.0.6)(debug@4.4.3): - dependencies: - '@types/http-proxy': 1.17.17 - http-proxy: 1.18.1(debug@4.4.3) - is-glob: 4.0.3 - is-plain-obj: 3.0.0 - micromatch: 4.0.8 - optionalDependencies: - '@types/express': 5.0.6 - transitivePeerDependencies: - - debug - - http-proxy@1.18.1(debug@4.4.3): - dependencies: - eventemitter3: 4.0.7 - follow-redirects: 1.15.11(debug@4.4.3) - requires-port: 1.0.0 - transitivePeerDependencies: - - debug - - https-proxy-agent@7.0.6: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - human-signals@2.1.0: {} - - human-signals@5.0.0: {} - - husky@9.1.7: {} - - iconv-lite@0.7.2: - dependencies: - safer-buffer: 2.1.2 - - ignore-by-default@1.0.1: {} + escape-string-regexp@4.0.0: {} - ignore@5.3.2: {} - - ignore@7.0.5: {} - - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.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 eslint-scope@8.4.0: dependencies: @@ -8675,7 +8196,7 @@ snapshots: events-universal@1.0.1: dependencies: - bare-events: 2.9.1 + bare-events: 2.9.2 transitivePeerDependencies: - bare-abort-controller @@ -8714,11 +8235,11 @@ snapshots: jest-mock: 30.4.1 jest-util: 30.4.1 - express-rate-limit@8.6.1(express@5.2.1): + express-rate-limit@8.6.2(express@5.2.1): dependencies: debug: 4.4.3(supports-color@5.5.0) express: 5.2.1 - ip-address: 10.4.0 + ip-address: 10.5.0 transitivePeerDependencies: - supports-color @@ -8787,7 +8308,7 @@ snapshots: fast-sha256@1.3.0: {} - fast-uri@3.1.5: {} + fast-uri@3.1.6: {} fb-watchman@2.0.2: dependencies: @@ -8797,9 +8318,9 @@ snapshots: dependencies: pend: 1.2.0 - fdir@6.5.0(picomatch@4.0.5): + fdir@6.5.0(picomatch@4.0.7): optionalDependencies: - picomatch: 4.0.5 + picomatch: 4.0.7 fetch-blob@3.2.0: dependencies: @@ -8898,7 +8419,7 @@ snapshots: function-bind@1.1.2: {} - gaxios@7.3.0: + gaxios@7.3.1: dependencies: extend: 3.0.2 https-proxy-agent: 7.0.6 @@ -8908,7 +8429,7 @@ snapshots: gcp-metadata@8.1.2: dependencies: - gaxios: 7.3.0 + gaxios: 7.3.1 google-logging-utils: 1.1.3 json-bigint: 1.0.0 transitivePeerDependencies: @@ -9014,7 +8535,7 @@ snapshots: dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.3.0 + gaxios: 7.3.1 gcp-metadata: 8.1.2 google-logging-utils: 1.1.3 jws: 4.0.1 @@ -9087,532 +8608,72 @@ snapshots: transitivePeerDependencies: - debug - imurmurhash@0.1.4: {} + http-proxy@1.18.1(debug@4.4.3): + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.16.0(debug@4.4.3) + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + human-signals@5.0.0: {} + + husky@9.1.7: {} + + iconv-lite@0.7.3: + dependencies: + safer-buffer: 2.1.2 - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 + ieee754@1.2.1: {} - inherits@2.0.4: {} + ignore-by-default@1.0.1: {} - ioredis@6.0.0: - dependencies: - '@ioredis/commands': 2.0.0 - cluster-key-slot: 1.1.1 - debug: 4.4.3(supports-color@5.5.0) - denque: 2.1.0 - redis-errors: 1.2.0 - standard-as-callback: 2.1.0 - transitivePeerDependencies: - - supports-color - - ip-address@10.1.0: {} - - ipaddr.js@1.9.1: {} - - is-arrayish@0.2.1: {} - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-fullwidth-code-point@4.0.0: {} - - is-fullwidth-code-point@5.1.0: - dependencies: - get-east-asian-width: 1.5.0 - - is-generator-fn@2.1.0: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - is-plain-obj@3.0.0: {} - - is-promise@4.0.0: {} - - is-stream@2.0.1: {} - - is-stream@3.0.0: {} - - isarray@1.0.0: {} - - isexe@2.0.0: {} - - istanbul-lib-coverage@3.2.2: {} - - istanbul-lib-instrument@6.0.3: - dependencies: - '@babel/core': 7.29.0 - '@babel/parser': 7.29.2 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.7.4 - transitivePeerDependencies: - - supports-color - - istanbul-lib-report@3.0.1: - dependencies: - istanbul-lib-coverage: 3.2.2 - make-dir: 4.0.0 - supports-color: 7.2.0 - - istanbul-lib-source-maps@5.0.6: - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - debug: 4.4.3(supports-color@5.5.0) - istanbul-lib-coverage: 3.2.2 - transitivePeerDependencies: - - supports-color - - istanbul-reports@3.2.0: - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 - - jackspeak@3.4.3: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - jest-changed-files@30.3.0: - dependencies: - execa: 5.1.1 - jest-util: 30.3.0 - p-limit: 3.1.0 - - jest-circus@30.3.0: - dependencies: - '@jest/environment': 30.3.0 - '@jest/expect': 30.3.0 - '@jest/test-result': 30.3.0 - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.7.2 - is-generator-fn: 2.1.0 - jest-each: 30.3.0 - jest-matcher-utils: 30.3.0 - jest-message-util: 30.3.0 - jest-runtime: 30.3.0 - jest-snapshot: 30.3.0 - jest-util: 30.3.0 - p-limit: 3.1.0 - pretty-format: 30.3.0 - pure-rand: 7.0.1 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-cli@30.3.0(@types/node@22.19.15)(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3)): - dependencies: - '@jest/core': 30.3.0(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3)) - '@jest/test-result': 30.3.0 - '@jest/types': 30.3.0 - chalk: 4.1.2 - exit-x: 0.2.2 - import-local: 3.2.0 - jest-config: 30.3.0(@types/node@22.19.15)(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3)) - jest-util: 30.3.0 - jest-validate: 30.3.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - esbuild-register - - supports-color - - ts-node - - jest-config@30.3.0(@types/node@22.19.15)(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3)): - dependencies: - '@babel/core': 7.29.0 - '@jest/get-type': 30.1.0 - '@jest/pattern': 30.0.1 - '@jest/test-sequencer': 30.3.0 - '@jest/types': 30.3.0 - babel-jest: 30.3.0(@babel/core@7.29.0) - chalk: 4.1.2 - ci-info: 4.4.0 - deepmerge: 4.3.1 - glob: 10.5.0 - graceful-fs: 4.2.11 - jest-circus: 30.3.0 - jest-docblock: 30.2.0 - jest-environment-node: 30.3.0 - jest-regex-util: 30.0.1 - jest-resolve: 30.3.0 - jest-runner: 30.3.0 - jest-util: 30.3.0 - jest-validate: 30.3.0 - parse-json: 5.2.0 - pretty-format: 30.3.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 22.19.15 - ts-node: 10.9.2(@types/node@22.19.15)(typescript@5.9.3) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-diff@30.3.0: - dependencies: - '@jest/diff-sequences': 30.3.0 - '@jest/get-type': 30.1.0 - chalk: 4.1.2 - pretty-format: 30.3.0 - - jest-docblock@30.2.0: - dependencies: - detect-newline: 3.1.0 - - jest-each@30.3.0: - dependencies: - '@jest/get-type': 30.1.0 - '@jest/types': 30.3.0 - chalk: 4.1.2 - jest-util: 30.3.0 - pretty-format: 30.3.0 - - jest-environment-node@30.3.0: - dependencies: - '@jest/environment': 30.3.0 - '@jest/fake-timers': 30.3.0 - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - jest-mock: 30.3.0 - jest-util: 30.3.0 - jest-validate: 30.3.0 - - jest-haste-map@30.3.0: - dependencies: - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 30.0.1 - jest-util: 30.3.0 - jest-worker: 30.3.0 - picomatch: 4.0.3 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - - jest-leak-detector@30.3.0: - dependencies: - '@jest/get-type': 30.1.0 - pretty-format: 30.3.0 - - jest-matcher-utils@30.3.0: - dependencies: - '@jest/get-type': 30.1.0 - chalk: 4.1.2 - jest-diff: 30.3.0 - pretty-format: 30.3.0 - - jest-message-util@30.3.0: - dependencies: - '@babel/code-frame': 7.29.0 - '@jest/types': 30.3.0 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - picomatch: 4.0.3 - pretty-format: 30.3.0 - slash: 3.0.0 - stack-utils: 2.0.6 - - jest-mock@30.3.0: - dependencies: - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - jest-util: 30.3.0 - - jest-pnp-resolver@1.2.3(jest-resolve@30.3.0): - optionalDependencies: - jest-resolve: 30.3.0 - - jest-regex-util@30.0.1: {} - - jest-resolve-dependencies@30.3.0: - dependencies: - jest-regex-util: 30.0.1 - jest-snapshot: 30.3.0 - transitivePeerDependencies: - - supports-color - - jest-resolve@30.3.0: - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 30.3.0 - jest-pnp-resolver: 1.2.3(jest-resolve@30.3.0) - jest-util: 30.3.0 - jest-validate: 30.3.0 - slash: 3.0.0 - unrs-resolver: 1.11.1 - - jest-runner@30.3.0: - dependencies: - '@jest/console': 30.3.0 - '@jest/environment': 30.3.0 - '@jest/test-result': 30.3.0 - '@jest/transform': 30.3.0 - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - chalk: 4.1.2 - emittery: 0.13.1 - exit-x: 0.2.2 - graceful-fs: 4.2.11 - jest-docblock: 30.2.0 - jest-environment-node: 30.3.0 - jest-haste-map: 30.3.0 - jest-leak-detector: 30.3.0 - jest-message-util: 30.3.0 - jest-resolve: 30.3.0 - jest-runtime: 30.3.0 - jest-util: 30.3.0 - jest-watcher: 30.3.0 - jest-worker: 30.3.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - - jest-runtime@30.3.0: - dependencies: - '@jest/environment': 30.3.0 - '@jest/fake-timers': 30.3.0 - '@jest/globals': 30.3.0 - '@jest/source-map': 30.0.1 - '@jest/test-result': 30.3.0 - '@jest/transform': 30.3.0 - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - chalk: 4.1.2 - cjs-module-lexer: 2.2.0 - collect-v8-coverage: 1.0.3 - glob: 10.5.0 - graceful-fs: 4.2.11 - jest-haste-map: 30.3.0 - jest-message-util: 30.3.0 - jest-mock: 30.3.0 - jest-regex-util: 30.0.1 - jest-resolve: 30.3.0 - jest-snapshot: 30.3.0 - jest-util: 30.3.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - - jest-snapshot@30.3.0: - dependencies: - '@babel/core': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) - '@babel/types': 7.29.0 - '@jest/expect-utils': 30.3.0 - '@jest/get-type': 30.1.0 - '@jest/snapshot-utils': 30.3.0 - '@jest/transform': 30.3.0 - '@jest/types': 30.3.0 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) - chalk: 4.1.2 - expect: 30.3.0 - graceful-fs: 4.2.11 - jest-diff: 30.3.0 - jest-matcher-utils: 30.3.0 - jest-message-util: 30.3.0 - jest-util: 30.3.0 - pretty-format: 30.3.0 - semver: 7.7.4 - synckit: 0.11.12 - transitivePeerDependencies: - - supports-color - - jest-util@30.3.0: - dependencies: - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - chalk: 4.1.2 - ci-info: 4.4.0 - graceful-fs: 4.2.11 - picomatch: 4.0.3 - - jest-validate@30.3.0: - dependencies: - '@jest/get-type': 30.1.0 - '@jest/types': 30.3.0 - camelcase: 6.3.0 - chalk: 4.1.2 - leven: 3.1.0 - pretty-format: 30.3.0 - - jest-watcher@30.3.0: - dependencies: - '@jest/test-result': 30.3.0 - '@jest/types': 30.3.0 - '@types/node': 22.19.15 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 30.3.0 - string-length: 4.0.2 - - jest-worker@30.3.0: - dependencies: - '@types/node': 22.19.15 - '@ungap/structured-clone': 1.3.0 - jest-util: 30.3.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - jest@30.3.0(@types/node@22.19.15)(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3)): - dependencies: - '@jest/core': 30.3.0(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3)) - '@jest/types': 30.3.0 - import-local: 3.2.0 - jest-cli: 30.3.0(@types/node@22.19.15)(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3)) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - esbuild-register - - supports-color - - ts-node - - jiti@2.6.1: {} - - jpeg-exif@1.1.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 - - jsesc@3.1.0: {} - - json-bigint@1.0.0: - dependencies: - bignumber.js: 9.3.1 - - json-buffer@3.0.1: {} - - json-parse-even-better-errors@2.3.1: {} - - json-schema-to-openapi-schema@0.4.0: - dependencies: - '@cloudflare/json-schema-walker': 0.1.1 - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - json5@2.2.3: {} - - jsonwebtoken@9.0.3: - dependencies: - jws: 4.0.1 - lodash.includes: 4.3.0 - lodash.isboolean: 3.0.3 - lodash.isinteger: 4.0.4 - lodash.isnumber: 3.0.3 - lodash.isplainobject: 4.0.6 - lodash.isstring: 4.0.1 - lodash.once: 4.1.1 - ms: 2.1.3 - semver: 7.7.4 - - jwa@2.0.1: - dependencies: - buffer-equal-constant-time: 1.0.1 - ecdsa-sig-formatter: 1.0.11 - safe-buffer: 5.2.1 - - jws@4.0.1: - dependencies: - jwa: 2.0.1 - safe-buffer: 5.2.1 - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - leven@3.1.0: {} - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - lilconfig@3.1.3: {} - - linebreak@1.1.0: - dependencies: - base64-js: 0.0.8 - unicode-trie: 2.0.0 - - lines-and-columns@1.2.4: {} - - lint-staged@15.5.2: - dependencies: - chalk: 5.6.2 - commander: 13.1.0 - debug: 4.4.3(supports-color@5.5.0) - execa: 8.0.1 - lilconfig: 3.1.3 - listr2: 8.3.3 - micromatch: 4.0.8 - pidtree: 0.6.0 - string-argv: 0.3.2 - yaml: 2.8.3 - transitivePeerDependencies: - - supports-color + ignore@5.3.2: {} - listr2@8.3.3: - dependencies: - cli-truncate: 4.0.0 - colorette: 2.0.20 - eventemitter3: 5.0.4 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 9.0.2 + ignore@7.0.6: {} - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + imurmurhash@0.1.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 - lodash.get@4.4.2: {} + inherits@2.0.4: {} - lodash.includes@4.3.0: {} + ioredis@6.0.0: + dependencies: + '@ioredis/commands': 2.0.0 + cluster-key-slot: 1.1.1 + debug: 4.4.3(supports-color@5.5.0) + denque: 2.1.0 + redis-errors: 1.2.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color - lodash.isboolean@3.0.3: {} + ip-address@10.5.0: {} - lodash.isequal@4.5.0: {} + ipaddr.js@1.9.1: {} is-arrayish@0.2.1: {} @@ -9821,7 +8882,7 @@ snapshots: jest-regex-util: 30.4.0 jest-util: 30.4.1 jest-worker: 30.4.1 - picomatch: 4.0.5 + picomatch: 4.0.7 walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 @@ -9846,7 +8907,7 @@ snapshots: chalk: 4.1.2 graceful-fs: 4.2.11 jest-util: 30.4.1 - picomatch: 4.0.5 + picomatch: 4.0.7 pretty-format: 30.4.1 slash: 3.0.0 stack-utils: 2.0.6 @@ -9919,7 +8980,7 @@ snapshots: '@jest/types': 30.4.1 '@types/node': 22.20.1 chalk: 4.1.2 - cjs-module-lexer: 2.2.0 + cjs-module-lexer: 2.2.1 collect-v8-coverage: 1.0.3 glob: 10.5.0 graceful-fs: 4.2.11 @@ -9968,7 +9029,7 @@ snapshots: chalk: 4.1.2 ci-info: 4.4.0 graceful-fs: 4.2.11 - picomatch: 4.0.5 + picomatch: 4.0.7 jest-validate@30.4.1: dependencies: @@ -9993,7 +9054,7 @@ snapshots: jest-worker@30.4.1: dependencies: '@types/node': 22.20.1 - '@ungap/structured-clone': 1.3.3 + '@ungap/structured-clone': 1.3.4 jest-util: 30.4.1 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -10078,1124 +9139,400 @@ snapshots: dependencies: json-buffer: 3.0.1 - lodash.isnumber@3.0.3: {} + leven@3.1.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 - lodash.isplainobject@4.0.6: {} + lilconfig@3.1.3: {} - lodash.isstring@4.0.1: {} + linebreak@1.1.0: + dependencies: + base64-js: 0.0.8 + unicode-trie: 2.0.0 - lodash.memoize@4.1.2: {} + lines-and-columns@1.2.4: {} - lodash.merge@4.6.2: {} + lint-staged@15.5.2: + dependencies: + chalk: 5.6.2 + commander: 13.1.0 + debug: 4.4.3(supports-color@5.5.0) + execa: 8.0.1 + lilconfig: 3.1.3 + listr2: 8.3.3 + micromatch: 4.0.8 + pidtree: 0.6.1 + string-argv: 0.3.2 + yaml: 2.9.0 + transitivePeerDependencies: + - supports-color - lodash.mergewith@4.6.2: {} + listr2@8.3.3: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.4 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 - lodash.once@4.1.1: {} + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 - lodash@4.17.23: {} + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 - log-update@6.1.0: - dependencies: - ansi-escapes: 7.3.0 - cli-cursor: 5.0.0 - slice-ansi: 7.1.2 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 + lodash.includes@4.3.0: {} - lru-cache@10.4.3: {} + lodash.isboolean@3.0.3: {} - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 + lodash.isinteger@4.0.4: {} - lru-cache@7.18.3: {} + lodash.isnumber@3.0.3: {} - make-dir@4.0.0: - dependencies: - semver: 7.7.4 + lodash.isplainobject@4.0.6: {} - make-error@1.3.6: {} + lodash.isstring@4.0.1: {} - makeerror@1.0.12: - dependencies: - tmpl: 1.0.5 + lodash.memoize@4.1.2: {} - math-intrinsics@1.1.0: {} + lodash.merge@4.6.2: {} - media-typer@0.3.0: {} + lodash.mergewith@4.6.2: {} - media-typer@1.1.0: {} + lodash.once@4.1.1: {} - merge-descriptors@2.0.0: {} + lodash@4.18.1: {} - merge-stream@2.0.0: {} + log-update@6.1.0: + dependencies: + ansi-escapes: 7.3.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 - methods@1.1.2: {} + lru-cache@10.4.3: {} - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 + lru-cache@11.5.2: {} - mime-db@1.52.0: {} + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 - mime-db@1.54.0: {} + lru-cache@7.18.3: {} - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 + make-dir@4.0.0: + dependencies: + semver: 7.8.5 - mime-types@3.0.2: - dependencies: - mime-db: 1.54.0 + make-error@1.3.6: {} - mime@2.6.0: {} + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 - mimic-fn@2.1.0: {} + math-intrinsics@1.1.0: {} - mimic-fn@4.0.0: {} + media-typer@0.3.0: {} - mimic-function@5.0.1: {} + media-typer@1.1.1: {} - minimatch@10.2.4: - dependencies: - brace-expansion: 5.0.4 + merge-descriptors@2.0.0: {} - minimatch@3.1.5: - dependencies: - brace-expansion: 1.1.12 + merge-stream@2.0.0: {} - minimatch@5.1.9: - dependencies: - brace-expansion: 2.0.2 + methods@1.1.2: {} - minimatch@9.0.9: - dependencies: - brace-expansion: 2.0.2 + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 - minimist@1.2.8: {} + mime-db@1.52.0: {} - minipass@7.1.3: {} + mime-db@1.54.0: {} - mitt@3.0.1: {} + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 - morgan@1.10.1: - dependencies: - basic-auth: 2.0.1 - debug: 2.6.9 - depd: 2.0.0 - on-finished: 2.3.0 - on-headers: 1.1.0 - transitivePeerDependencies: - - supports-color + mime@2.6.0: {} - ms@2.0.0: {} + mimic-fn@2.1.0: {} - ms@2.1.3: {} + mimic-fn@4.0.0: {} - multer@1.4.5-lts.2: - dependencies: - append-field: 1.0.0 - busboy: 1.6.0 - concat-stream: 1.6.2 - mkdirp: 0.5.6 - object-assign: 4.1.1 - type-is: 1.6.18 - xtend: 4.0.2 + mimic-function@5.0.1: {} - napi-postinstall@0.3.4: {} + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.9 - natural-compare@1.4.0: {} + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.18 - negotiator@1.0.0: {} + minimatch@5.1.9: + dependencies: + brace-expansion: 2.1.4 - neo-async@2.6.2: {} + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.4 - netmask@2.0.2: {} + minimist@1.2.8: {} - node-addon-api@8.6.0: {} + minipass@7.1.3: {} - node-domexception@1.0.0: {} + mitt@3.0.1: {} - node-fetch-native@1.6.7: {} + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 - node-fetch@3.3.2: - dependencies: - data-uri-to-buffer: 4.0.1 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 + morgan@1.11.0: + dependencies: + basic-auth: 2.0.1 + debug: 2.6.9 + depd: 2.0.0 + on-finished: 2.4.1 + on-headers: 1.1.0 + transitivePeerDependencies: + - supports-color - node-gyp-build@4.8.4: {} + ms@2.0.0: {} - node-int64@0.4.0: {} + ms@2.1.3: {} - node-releases@2.0.36: {} + multer@1.4.5-lts.2: + dependencies: + append-field: 1.0.0 + busboy: 1.6.0 + concat-stream: 1.6.2 + mkdirp: 0.5.6 + object-assign: 4.1.1 + type-is: 1.6.18 + xtend: 4.0.2 - nodemailer@7.0.13: {} + napi-postinstall@0.3.4: {} - nodemon@3.1.14: - dependencies: - chokidar: 3.6.0 - debug: 4.4.3(supports-color@5.5.0) - ignore-by-default: 1.0.1 - minimatch: 10.2.4 - pstree.remy: 1.1.8 - semver: 7.7.4 - simple-update-notifier: 2.0.0 - supports-color: 5.5.0 - touch: 3.1.1 - undefsafe: 2.0.5 + natural-compare@1.4.0: {} - normalize-path@3.0.0: {} + negotiator@1.1.0: + dependencies: + content-type: 2.1.0 - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 + neo-async@2.6.2: {} - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 + netmask@2.1.1: {} - nypm@0.6.5: - dependencies: - citty: 0.2.1 - pathe: 2.0.3 - tinyexec: 1.0.4 + node-addon-api@8.9.2: {} - object-assign@4.1.1: {} + node-domexception@1.0.0: {} - object-inspect@1.13.4: {} + node-fetch-native@1.6.7: {} - ohash@2.0.11: {} + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 - on-exit-leak-free@2.1.2: {} + node-gyp-build@4.8.4: {} - on-finished@2.3.0: - dependencies: - ee-first: 1.1.1 + node-int64@0.4.0: {} - on-finished@2.4.1: - dependencies: - ee-first: 1.1.1 + node-releases@2.0.53: {} - on-headers@1.1.0: {} + nodemailer@7.0.13: {} - once@1.4.0: - dependencies: - wrappy: 1.0.2 + nodemon@3.1.14: + dependencies: + chokidar: 3.6.0 + debug: 4.4.3(supports-color@5.5.0) + ignore-by-default: 1.0.1 + minimatch: 10.2.6 + pstree.remy: 1.1.8 + semver: 7.8.5 + simple-update-notifier: 2.0.0 + supports-color: 5.5.0 + touch: 3.1.1 + undefsafe: 2.0.5 - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 + normalize-path@3.0.0: {} - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 - onetime@7.0.0: - dependencies: - mimic-function: 5.0.1 + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 - openapi-types@12.1.3: {} + nypm@0.6.9: + dependencies: + citty: 0.2.2 + pathe: 2.0.3 + tinyexec: 1.3.0 - opentype.js@0.11.0: - dependencies: - string.prototype.codepointat: 0.2.1 - tiny-inflate: 1.0.3 + object-assign@4.1.1: {} - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 + object-inspect@1.13.4: {} - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 + ohash@2.0.12: {} - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 + on-exit-leak-free@2.1.2: {} - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 + on-headers@1.1.0: {} - p-try@2.2.0: {} + once@1.4.0: + dependencies: + wrappy: 1.0.2 - pac-proxy-agent@7.2.0: - dependencies: - '@tootallnate/quickjs-emscripten': 0.23.0 - agent-base: 7.1.4 - debug: 4.4.3(supports-color@5.5.0) - 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 + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 - pac-resolver@7.0.1: - dependencies: - degenerator: 5.0.1 - netmask: 2.0.2 + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 - package-json-from-dist@1.0.1: {} + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 - pako@0.2.9: {} + openapi-types@12.1.3: {} - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 + opentype.js@0.11.0: + dependencies: + string.prototype.codepointat: 0.2.1 + tiny-inflate: 1.0.3 - 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 + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 - parseurl@1.3.3: {} + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 - path-equal@1.2.5: {} + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 - path-exists@4.0.0: {} + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 - path-is-absolute@1.0.1: {} + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 - path-key@3.1.1: {} + p-try@2.2.0: {} - path-key@4.0.0: {} + pac-proxy-agent@7.2.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.4 + debug: 4.4.3(supports-color@5.5.0) + 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 - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.3 + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.1.1 - path-to-regexp@8.3.0: {} + package-json-from-dist@1.0.1: {} - pathe@2.0.3: {} + pako@0.2.9: {} - pdfkit@0.17.2: - dependencies: - crypto-js: 4.2.0 - fontkit: 2.0.4 - jpeg-exif: 1.1.4 - linebreak: 1.1.0 - png-js: 1.0.0 + pako@1.0.11: {} - pend@1.2.0: {} + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 - perfect-debounce@1.0.0: {} + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.7 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 - picocolors@1.1.1: {} + parseurl@1.3.3: {} - picomatch@2.3.1: {} + path-equal@1.2.5: {} - picomatch@4.0.3: {} + path-exists@4.0.0: {} - pidtree@0.6.0: {} - - pino-abstract-transport@2.0.0: - dependencies: - split2: 4.2.0 - - pino-std-serializers@7.1.0: {} - - pino@9.14.0: - dependencies: - '@pinojs/redact': 0.4.0 - atomic-sleep: 1.0.0 - on-exit-leak-free: 2.1.2 - pino-abstract-transport: 2.0.0 - pino-std-serializers: 7.1.0 - process-warning: 5.0.0 - quick-format-unescaped: 4.0.4 - real-require: 0.2.0 - safe-stable-stringify: 2.5.0 - sonic-boom: 4.2.1 - thread-stream: 3.1.0 - - pirates@4.0.7: {} - - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - - pkg-types@2.3.0: - dependencies: - confbox: 0.2.4 - exsolve: 1.0.8 - pathe: 2.0.3 - - png-js@1.0.0: {} - - postal-mime@2.7.3: {} + path-is-absolute@1.0.1: {} - prelude-ls@1.2.1: {} + path-key@3.1.1: {} - prettier@3.8.1: {} - - pretty-format@30.3.0: - dependencies: - '@jest/schemas': 30.0.5 - ansi-styles: 5.2.0 - react-is: 18.3.1 - - prisma@6.19.2(typescript@5.9.3): - dependencies: - '@prisma/config': 6.19.2 - '@prisma/engines': 6.19.2 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - magicast - - process-nextick-args@2.0.1: {} - - process-warning@5.0.0: {} - - progress@2.0.3: {} - - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - - proxy-agent@6.5.0: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3(supports-color@5.5.0) - 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: {} - - pstree.remy@1.1.8: {} - - 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(supports-color@5.5.0) - 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@5.9.3): - dependencies: - '@puppeteer/browsers': 2.13.0 - chromium-bidi: 14.0.0(devtools-protocol@0.0.1581282) - cosmiconfig: 9.0.1(typescript@5.9.3) - 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 - - pure-rand@6.1.0: {} - - pure-rand@7.0.1: {} - - qs@6.15.0: - dependencies: - side-channel: 1.1.0 - - quick-format-unescaped@4.0.4: {} - - range-parser@1.2.1: {} - - raw-body@3.0.2: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.1 - iconv-lite: 0.7.2 - unpipe: 1.0.0 - - rc9@2.1.2: - dependencies: - defu: 6.1.4 - destr: 2.0.5 - - react-is@18.3.1: {} - - readable-stream@2.3.8: - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - readdirp@4.1.2: {} - - real-require@0.2.0: {} - - redis-errors@1.2.0: {} - - require-directory@2.1.1: {} - - requires-port@1.0.0: {} - - resend@6.9.4: - dependencies: - postal-mime: 2.7.3 - svix: 1.86.0 - - resolve-cwd@3.0.0: - dependencies: - resolve-from: 5.0.0 - - resolve-from@4.0.0: {} - - resolve-from@5.0.0: {} - - restore-cursor@5.1.0: - dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 - - restructure@3.0.2: {} - - rfdc@1.4.1: {} - - router@2.2.0: - dependencies: - debug: 4.4.3(supports-color@5.5.0) - depd: 2.0.0 - is-promise: 4.0.0 - parseurl: 1.3.3 - path-to-regexp: 8.3.0 - transitivePeerDependencies: - - supports-color - - safe-buffer@5.1.2: {} - - safe-buffer@5.2.1: {} - - safe-stable-stringify@2.5.0: {} - - safer-buffer@2.1.2: {} - - semver@6.3.1: {} - - semver@7.7.4: {} - - send@1.2.1: - dependencies: - debug: 4.4.3(supports-color@5.5.0) - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 2.0.0 - http-errors: 2.0.1 - mime-types: 3.0.2 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - - serve-static@2.2.1: - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 1.2.1 - transitivePeerDependencies: - - supports-color - - setprototypeof@1.2.0: {} - - 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: {} - - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - signal-exit@3.0.7: {} - - signal-exit@4.1.0: {} - - simple-update-notifier@2.0.0: - dependencies: - semver: 7.7.4 - - slash@3.0.0: {} - - slice-ansi@5.0.0: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 4.0.0 - - slice-ansi@7.1.2: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - - smart-buffer@4.2.0: {} - - socks-proxy-agent@8.0.5: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3(supports-color@5.5.0) - socks: 2.8.7 - transitivePeerDependencies: - - supports-color - - socks@2.8.7: - dependencies: - ip-address: 10.1.0 - smart-buffer: 4.2.0 - - sonic-boom@4.2.1: - dependencies: - atomic-sleep: 1.0.0 - - source-map-support@0.5.13: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - - split2@4.2.0: {} - - sprintf-js@1.0.3: {} - - ssf@0.11.2: - dependencies: - frac: 1.1.2 - - stack-utils@2.0.6: - dependencies: - escape-string-regexp: 2.0.0 - - standard-as-callback@2.1.0: {} - - standardwebhooks@1.0.0: - dependencies: - '@stablelib/base64': 1.0.1 - fast-sha256: 1.3.0 - - statuses@2.0.2: {} - - streamsearch@1.1.0: {} - - 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-argv@0.3.2: {} - - string-length@4.0.2: - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.2.0 - - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.5.0 - strip-ansi: 7.2.0 - - string.prototype.codepointat@0.2.1: {} - - string_decoder@1.1.1: - dependencies: - safe-buffer: 5.1.2 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.2.0: - dependencies: - ansi-regex: 6.2.2 - - strip-bom@4.0.0: {} - - strip-final-newline@2.0.0: {} - - strip-final-newline@3.0.0: {} - - strip-json-comments@3.1.1: {} - - superagent@10.3.0: - dependencies: - component-emitter: 1.3.1 - cookiejar: 2.1.4 - debug: 4.4.3(supports-color@5.5.0) - fast-safe-stringify: 2.1.1 - form-data: 4.0.5 - formidable: 3.5.4 - methods: 1.1.2 - mime: 2.6.0 - qs: 6.15.0 - transitivePeerDependencies: - - supports-color - - supertest@7.2.2: - dependencies: - cookie-signature: 1.2.2 - methods: 1.1.2 - superagent: 10.3.0 - transitivePeerDependencies: - - supports-color - - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - svix@1.86.0: - dependencies: - standardwebhooks: 1.0.0 - uuid: 10.0.0 - - swagger-jsdoc@6.2.8(openapi-types@12.1.3): - dependencies: - commander: 6.2.0 - doctrine: 3.0.0 - glob: 7.1.6 - lodash.mergewith: 4.6.2 - swagger-parser: 10.0.3(openapi-types@12.1.3) - yaml: 2.0.0-1 - transitivePeerDependencies: - - openapi-types - - swagger-parser@10.0.3(openapi-types@12.1.3): - dependencies: - '@apidevtools/swagger-parser': 10.0.3(openapi-types@12.1.3) - transitivePeerDependencies: - - openapi-types - - swagger-ui-dist@5.32.1: - dependencies: - '@scarf/scarf': 1.4.0 - - swagger-ui-express@4.6.3(express@5.2.1): - dependencies: - express: 5.2.1 - swagger-ui-dist: 5.32.1 - - swagger-ui-express@5.0.1(express@5.2.1): - dependencies: - express: 5.2.1 - swagger-ui-dist: 5.32.1 - - synckit@0.11.12: - dependencies: - '@pkgr/core': 0.2.9 - - tar-fs@3.1.2: - dependencies: - pump: 3.0.4 - tar-stream: 3.1.8 - optionalDependencies: - bare-fs: 4.5.6 - 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.5.6 - 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 - - test-exclude@6.0.0: - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.5 - - text-decoder@1.2.7: - dependencies: - b4a: 1.8.0 - transitivePeerDependencies: - - react-native-b4a - - text-to-svg@3.1.5: - dependencies: - commander: 2.20.3 - opentype.js: 0.11.0 - - thread-stream@3.1.0: - dependencies: - real-require: 0.2.0 - - tiny-inflate@1.0.3: {} - - tinyexec@1.0.4: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - - tmpl@1.0.5: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - toidentifier@1.0.1: {} - - touch@3.1.1: {} - - ts-api-utils@2.5.0(typescript@5.9.3): - dependencies: - typescript: 5.9.3 - - ts-jest@29.4.6(@babel/core@7.29.0)(@jest/transform@30.3.0)(@jest/types@30.3.0)(babel-jest@30.3.0(@babel/core@7.29.0))(jest-util@30.3.0)(jest@30.3.0(@types/node@22.19.15)(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3)))(typescript@5.9.3): - dependencies: - bs-logger: 0.2.6 - fast-json-stable-stringify: 2.1.0 - handlebars: 4.7.9 - jest: 30.3.0(@types/node@22.19.15)(ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3)) - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.7.4 - type-fest: 4.41.0 - typescript: 5.9.3 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.29.0 - '@jest/transform': 30.3.0 - '@jest/types': 30.3.0 - babel-jest: 30.3.0(@babel/core@7.29.0) - jest-util: 30.3.0 - - ts-node@10.9.2(@types/node@18.19.130)(typescript@5.5.4): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 18.19.130 - acorn: 8.16.0 - acorn-walk: 8.3.5 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.4 - make-error: 1.3.6 - typescript: 5.5.4 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - - ts-node@10.9.2(@types/node@22.19.15)(typescript@5.9.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 22.19.15 - acorn: 8.16.0 - acorn-walk: 8.3.5 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.4 - make-error: 1.3.6 - typescript: 5.9.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - - tslib@2.8.1: {} - - tspec@0.1.120(@types/express@5.0.6)(express@5.2.1): - dependencies: - debug: 4.4.3(supports-color@5.5.0) - express: 5.2.1 - glob: 8.1.0 - http-proxy-middleware: 2.0.9(@types/express@5.0.6)(debug@4.4.3) - json-schema-to-openapi-schema: 0.4.0 - openapi-types: 12.1.3 - swagger-ui-express: 4.6.3(express@5.2.1) - typescript: 5.6.3 - typescript-json-schema: 0.65.1 - yargs: 17.7.2 - transitivePeerDependencies: - - '@swc/core' - - '@swc/wasm' - - '@types/express' - - supports-color - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - type-detect@4.0.8: {} - - type-fest@0.21.3: {} - - type-fest@4.41.0: {} - - type-is@1.6.18: - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - - type-is@2.0.1: - dependencies: - content-type: 1.0.5 - media-typer: 1.1.0 - mime-types: 3.0.2 - - typed-query-selector@2.12.1: {} - - typedarray@0.0.6: {} - - typescript-json-schema@0.65.1: - dependencies: - '@types/json-schema': 7.0.15 - '@types/node': 18.19.130 - glob: 7.2.3 - path-equal: 1.2.5 - safe-stable-stringify: 2.5.0 - ts-node: 10.9.2(@types/node@18.19.130)(typescript@5.5.4) - typescript: 5.5.4 - yargs: 17.7.2 - transitivePeerDependencies: - - '@swc/core' - - '@swc/wasm' - - typescript@5.5.4: {} - - typescript@5.6.3: {} - - typescript@5.9.3: {} - - uglify-js@3.19.3: - optional: true - - undefsafe@2.0.5: {} - - undici-types@5.26.5: {} - - undici-types@6.21.0: {} - - unicode-properties@1.4.1: - dependencies: - base64-js: 1.5.1 - unicode-trie: 2.0.0 - - unicode-trie@2.0.0: - dependencies: - pako: 0.2.9 - tiny-inflate: 1.0.3 - - unpipe@1.0.0: {} - - unrs-resolver@1.11.1: - dependencies: - napi-postinstall: 0.3.4 - optionalDependencies: - '@unrs/resolver-binding-android-arm-eabi': 1.11.1 - '@unrs/resolver-binding-android-arm64': 1.11.1 - '@unrs/resolver-binding-darwin-arm64': 1.11.1 - '@unrs/resolver-binding-darwin-x64': 1.11.1 - '@unrs/resolver-binding-freebsd-x64': 1.11.1 - '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 - '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 - '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 - '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 - '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 - '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-x64-musl': 1.11.1 - '@unrs/resolver-binding-wasm32-wasi': 1.11.1 - '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 - '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 - '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - - update-browserslist-db@1.2.3(browserslist@4.28.1): - dependencies: - browserslist: 4.28.1 - escalade: 3.2.0 - picocolors: 1.1.1 + path-key@4.0.0: {} - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 - util-deprecate@1.0.2: {} + path-scurry@2.0.2: + dependencies: + lru-cache: 11.5.2 + minipass: 7.1.3 - uuid@10.0.0: {} + path-to-regexp@8.4.2: {} - v8-compile-cache-lib@3.0.1: {} + pathe@2.0.3: {} - v8-to-istanbul@9.3.0: - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 + pdfkit@0.17.2: + dependencies: + crypto-js: 4.2.0 + fontkit: 2.0.4 + jpeg-exif: 1.1.4 + linebreak: 1.1.0 + png-js: 1.1.0 - validator@13.15.26: {} + pend@1.2.0: {} - vary@1.1.2: {} + perfect-debounce@1.0.0: {} - walker@1.0.8: - dependencies: - makeerror: 1.0.12 + picocolors@1.1.1: {} - web-streams-polyfill@3.3.3: {} + picomatch@2.3.2: {} - webdriver-bidi-protocol@0.4.1: {} + picomatch@4.0.7: {} - which@2.0.2: - dependencies: - isexe: 2.0.0 + pidtree@0.6.1: {} - wmf@1.0.2: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 pino-abstract-transport@3.0.0: dependencies: @@ -11219,9 +9556,132 @@ snapshots: pino-std-serializers@7.1.0: {} - word@0.3.0: {} + pino@9.14.0: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.1.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.1 + thread-stream: 3.2.0 + + pirates@4.0.7: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + pkg-types@2.3.1: + dependencies: + confbox: 0.2.4 + exsolve: 1.1.1 + pathe: 2.0.3 + + png-js@1.1.0: + dependencies: + browserify-zlib: 0.2.0 + + possible-typed-array-names@1.1.0: {} + + postal-mime@2.7.5: {} + + prelude-ls@1.2.1: {} + + prettier@3.9.6: {} + + pretty-format@30.4.1: + dependencies: + '@jest/schemas': 30.4.1 + ansi-styles: 5.2.0 + react-is-18: react-is@18.3.1 + react-is-19: react-is@19.2.8 + + prisma@6.19.3(typescript@5.9.3): + dependencies: + '@prisma/config': 6.19.3 + '@prisma/engines': 6.19.3 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - magicast + + process-nextick-args@2.0.1: {} + + process-warning@5.1.0: {} + + progress@2.0.3: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-agent@6.5.0: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@5.5.0) + 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: {} + + pstree.remy@1.1.8: {} + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + punycode@2.3.1: {} + + puppeteer-core@24.43.1: + dependencies: + '@puppeteer/browsers': 2.13.2 + chromium-bidi: 14.0.0(devtools-protocol@0.0.1608973) + debug: 4.4.3(supports-color@5.5.0) + devtools-protocol: 0.0.1608973 + typed-query-selector: 2.12.2 + webdriver-bidi-protocol: 0.4.1 + ws: 8.21.3 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - bufferutil + - react-native-b4a + - supports-color + - utf-8-validate + + puppeteer@24.43.1(typescript@5.9.3): + dependencies: + '@puppeteer/browsers': 2.13.2 + chromium-bidi: 14.0.0(devtools-protocol@0.0.1608973) + cosmiconfig: 9.0.2(typescript@5.9.3) + devtools-protocol: 0.0.1608973 + puppeteer-core: 24.43.1 + typed-query-selector: 2.12.2 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - bufferutil + - react-native-b4a + - supports-color + - typescript + - utf-8-validate + + pure-rand@6.1.0: {} - wordwrap@1.0.0: {} + pure-rand@7.0.1: {} qs@6.15.3: dependencies: @@ -11268,17 +9728,13 @@ snapshots: redis-errors@1.2.0: {} - redis-parser@3.0.0: - dependencies: - redis-errors: 1.2.0 - require-directory@2.1.1: {} require-from-string@2.0.2: {} requires-port@1.0.0: {} - resend@6.18.1: + resend@6.24.0: dependencies: postal-mime: 2.7.5 standardwebhooks: 1.0.0 @@ -11463,7 +9919,7 @@ snapshots: socks@2.8.9: dependencies: - ip-address: 10.4.0 + ip-address: 10.5.0 smart-buffer: 4.2.0 sonic-boom@4.2.1: @@ -11500,7 +9956,7 @@ snapshots: streamsearch@1.1.0: {} - streamx@2.28.0: + streamx@2.28.1: dependencies: events-universal: 1.0.1 fast-fifo: 1.3.2 @@ -11546,7 +10002,7 @@ snapshots: strip-ansi@7.2.0: dependencies: - ansi-regex: 6.2.2 + ansi-regex: 6.3.0 strip-bom@4.0.0: {} @@ -11603,19 +10059,19 @@ snapshots: transitivePeerDependencies: - openapi-types - swagger-ui-dist@5.32.11: + swagger-ui-dist@5.32.14: dependencies: '@scarf/scarf': 1.4.0 swagger-ui-express@4.6.3(express@5.2.1): dependencies: express: 5.2.1 - swagger-ui-dist: 5.32.11 + swagger-ui-dist: 5.32.14 swagger-ui-express@5.0.1(express@5.2.1): dependencies: express: 5.2.1 - swagger-ui-dist: 5.32.11 + swagger-ui-dist: 5.32.14 synckit@0.11.13: dependencies: @@ -11624,21 +10080,21 @@ snapshots: tar-fs@3.1.3: dependencies: pump: 3.0.4 - tar-stream: 3.2.0 + tar-stream: 3.2.1 optionalDependencies: - bare-fs: 4.7.4 + bare-fs: 4.8.1 bare-path: 3.1.1 transitivePeerDependencies: - bare-abort-controller - bare-buffer - react-native-b4a - tar-stream@3.2.0: + tar-stream@3.2.1: dependencies: b4a: 1.8.1 - bare-fs: 4.7.4 + bare-fs: 4.8.1 fast-fifo: 1.3.2 - streamx: 2.28.0 + streamx: 2.28.1 transitivePeerDependencies: - bare-abort-controller - bare-buffer @@ -11646,7 +10102,7 @@ snapshots: teex@1.0.1: dependencies: - streamx: 2.28.0 + streamx: 2.28.1 transitivePeerDependencies: - bare-abort-controller - react-native-b4a @@ -11678,8 +10134,8 @@ snapshots: tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 tmpl@1.0.5: {} @@ -11724,7 +10180,7 @@ snapshots: ts-node@10.9.2(@types/node@18.19.130)(typescript@5.5.4): dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 + '@tsconfig/node10': 1.0.13 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 @@ -11742,7 +10198,7 @@ snapshots: ts-node@10.9.2(@types/node@22.20.1)(typescript@5.9.3): dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 + '@tsconfig/node10': 1.0.13 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 @@ -11794,7 +10250,7 @@ snapshots: type-is@2.1.0: dependencies: - content-type: 2.0.0 + content-type: 2.1.0 media-typer: 1.1.1 mime-types: 3.0.2 @@ -11876,9 +10332,9 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.12.2 '@unrs/resolver-binding-win32-x64-msvc': 1.12.2 - update-browserslist-db@1.2.3(browserslist@4.28.7): + update-browserslist-db@1.3.1(browserslist@4.28.8): dependencies: - browserslist: 4.28.7 + browserslist: 4.28.8 escalade: 3.2.0 picocolors: 1.1.1 @@ -11888,8 +10344,6 @@ snapshots: util-deprecate@1.0.2: {} - uuid@14.0.1: {} - v8-compile-cache-lib@3.0.1: {} v8-to-istanbul@9.3.0: @@ -11918,78 +10372,88 @@ snapshots: gopd: 1.2.0 has-tostringtag: 1.0.2 - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 5.1.2 - strip-ansi: 7.2.0 + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wmf@1.0.2: {} + + word-wrap@1.2.5: {} + + word@0.3.0: {} + + wordwrap@1.0.0: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.2.0 + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 - wrappy@1.0.2: {} + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 - write-file-atomic@5.0.1: - dependencies: - imurmurhash: 0.1.4 - signal-exit: 4.1.0 + wrappy@1.0.2: {} - ws@8.20.0: {} + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 - xlsx@0.18.5: - dependencies: - adler-32: 1.3.1 - cfb: 1.2.2 - codepage: 1.15.0 - crc-32: 1.2.2 - ssf: 0.11.2 - wmf: 1.0.2 - word: 0.3.0 + ws@8.21.3: {} - xtend@4.0.2: {} + xlsx@0.18.5: + dependencies: + adler-32: 1.3.1 + cfb: 1.2.2 + codepage: 1.15.0 + crc-32: 1.2.2 + ssf: 0.11.2 + wmf: 1.0.2 + word: 0.3.0 - y18n@5.0.8: {} + xtend@4.0.2: {} - yallist@3.1.1: {} + y18n@5.0.8: {} - yaml@2.0.0-1: {} + yallist@3.1.1: {} - yaml@2.8.3: {} + yaml@2.0.0-1: {} - yargs-parser@21.1.1: {} + yaml@2.9.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 + yargs-parser@21.1.1: {} - yauzl@2.10.0: - dependencies: - buffer-crc32: 0.2.13 - fd-slicer: 1.1.0 + yargs@17.7.3: + 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 - yn@3.1.1: {} + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 - yocto-queue@0.1.0: {} + yn@3.1.1: {} - z-schema@5.0.5: - dependencies: - lodash.get: 4.4.2 - lodash.isequal: 4.5.0 - validator: 13.15.26 - optionalDependencies: - commander: 9.5.0 + yocto-queue@0.1.0: {} - zod-validation-error@3.5.4(zod@3.25.76): - dependencies: - zod: 3.25.76 + zod-validation-error@3.5.4(zod@3.25.76): + dependencies: + zod: 3.25.76 - zod@3.25.76: {} + zod@3.25.76: {} diff --git a/prisma/schema/activity.prisma b/prisma/schema/activity.prisma index c0f842a..083bc9d 100644 --- a/prisma/schema/activity.prisma +++ b/prisma/schema/activity.prisma @@ -8,7 +8,12 @@ enum ActivityType { DIVIDEND_DISTRIBUTED KEYS_CLAIMED KEY_BURNED + KEY_TRANSFERRED + KEY_TRANSFERRED_IN + KEY_TRANSFERRED_OUT SUPPLY_CAP_SET + TRADING_PAUSE_PROPOSED + TRADING_PAUSE_APPROVED } model Activity { @@ -33,3 +38,24 @@ model Activity { @@index([actor]) @@index([type]) } + +model ActivityLog { + id String @id @default(cuid()) + type String // buy, sell, transfer_in, transfer_out, burn, dividend + actor String // wallet address + keyId String? + creatorName String? + amount Decimal? @default(0) + target String? + txHash String? + payload Json? + timestamp DateTime @default(now()) + createdAt DateTime @default(now()) + + @@unique([txHash, actor, type]) + @@index([actor]) + @@index([keyId]) + @@index([type]) + @@index([timestamp(sort: Desc)]) + @@map("activity_log") +} diff --git a/prisma/schema/dividend.prisma b/prisma/schema/dividend.prisma index 91d850e..54f7d16 100644 --- a/prisma/schema/dividend.prisma +++ b/prisma/schema/dividend.prisma @@ -4,9 +4,9 @@ model DividendDistribution { id String @id @default(cuid()) creatorId String distributionDate DateTime - totalAmountXlm Decimal @db.Numeric(20, 7) + totalAmountXlm Decimal @db.Decimal(20, 7) holderCount Int - perKeyAmountXlm Decimal @db.Numeric(20, 7) + perKeyAmountXlm Decimal @db.Decimal(20, 7) ledger Int txHash String createdAt DateTime @default(now()) @@ -22,7 +22,7 @@ model DividendClaim { id String @id @default(cuid()) distributionId String recipientAddress String - amountXlm Decimal @db.Numeric(20, 7) + amountXlm Decimal @db.Decimal(20, 7) claimedAt DateTime? createdAt DateTime @default(now()) diff --git a/prisma/schema/governance.prisma b/prisma/schema/governance.prisma index fa205b2..cc7e4eb 100644 --- a/prisma/schema/governance.prisma +++ b/prisma/schema/governance.prisma @@ -19,3 +19,19 @@ model GovernanceProposal { @@index([keyId, status]) @@index([keyId, expiresAt]) } + +model PauseProposal { + id String @id @default(cuid()) + proposalId String @unique + keyId String + proposerWallet String + approverWallet String? + txHash String? + status String @default("pending") // pending | executed | rejected | cancelled + createdAt DateTime @default(now()) + executedAt DateTime? + + @@index([keyId, status]) + @@index([proposerWallet]) + @@map("pause_proposals") +} diff --git a/prisma/schema/ownership.prisma b/prisma/schema/ownership.prisma index 9c803aa..705d50a 100644 --- a/prisma/schema/ownership.prisma +++ b/prisma/schema/ownership.prisma @@ -11,6 +11,7 @@ model KeyOwnership { // The amount of keys owned balance Decimal @default(0) + costBasis Decimal? @default(0) /// When the current lockup window ends for this holding, if any. lockupExpiresAt DateTime? diff --git a/src/config.schema.ts b/src/config.schema.ts index c732de8..453cacb 100644 --- a/src/config.schema.ts +++ b/src/config.schema.ts @@ -85,6 +85,10 @@ export const envSchema = z ENABLE_SCHEMA_VERSION_HEADER: booleanCoerce.default(true), ENABLE_REQUEST_LOGGING: booleanCoerce.default(true), DB_QUERY_TIMEOUT_MS: z.coerce.number().default(5000), + DB_POOL_WAIT_WARN_MS: z.coerce.number().int().positive().default(2000), + DB_POOL_WAIT_ERROR_MS: z.coerce.number().int().positive().default(5000), + WEBHOOK_MAX_PER_CREATOR: z.coerce.number().int().positive().default(5), + WEBHOOK_RETRY_MAX_ATTEMPTS: z.coerce.number().int().positive().default(3), APP_SECRET: z .string() diff --git a/src/constants/notifications.constants.ts b/src/constants/notifications.constants.ts index 7a848cc..0949440 100644 --- a/src/constants/notifications.constants.ts +++ b/src/constants/notifications.constants.ts @@ -4,6 +4,8 @@ export const NOTIFICATION_TYPES = { TRADE_COMPLETED: 'trade_completed', LOCKUP_EXPIRING: 'lockup_expiring', PRICE_MOVED: 'price_moved', + PAUSE_PROPOSAL_CREATED: 'pause_proposal_created', + TRADING_PAUSED: 'trading_paused', } as const; export type NotificationType = diff --git a/src/modules/admin/admin.routes.ts b/src/modules/admin/admin.routes.ts index b53d026..2ba70c7 100644 --- a/src/modules/admin/admin.routes.ts +++ b/src/modules/admin/admin.routes.ts @@ -9,13 +9,14 @@ import { } from './admin.controllers'; import { httpSyncKeyState } from './key-sync.controllers'; import { adminGuard, AdminRequest } from '../../middlewares/admin-guard.middleware'; -import { requireJwtAuth, requireKeyCreator, AuthenticatedRequest } from '../../middlewares/jwt-auth.middleware'; +import { requireKeyCreator, AuthenticatedRequest } from '../../middlewares/jwt-auth.middleware'; import { sendError, sendNotFound, sendSuccess, sendValidationError, sendConflict, + sendForbidden, zodIssuesToDetails, } from '../../utils/api-response.utils'; import { ErrorCode } from '../../constants/error.constants'; @@ -208,7 +209,7 @@ adminRouter.post('/timelock/:proposalId/cancel', adminGuard, async (req: AdminRe * * List all pending and executed timelock proposals. */ -adminRouter.get('/timelock/proposals', adminGuard, async (req: AdminRequest, res, next) => { +adminRouter.get('/timelock/proposals', adminGuard, async (_req: AdminRequest, res, next) => { try { const proposals = await prisma.governanceProposal.findMany({ where: { keyId: 'timelock' }, @@ -302,4 +303,150 @@ adminRouter.post('/creator/:keyId/supply-cap', requireKeyCreator('keyId'), async } }); + +// ── Multi-sig Pause Coordination (#826) ────────────────────────── + +/** + * POST /api/v1/admin/keys/:keyId/pause/propose + * Initiates a trading pause proposal requiring two distinct admin signatures. + */ +adminRouter.post("/keys/:keyId/pause/propose", adminGuard, async (req: AdminRequest, res, next) => { + try { + const keyId = String(req.params.keyId); + + const creator = await prisma.creatorProfile.findFirst({ + where: { OR: [{ id: keyId }, { handle: keyId }] }, + }); + + if (!creator) { + sendNotFound(res, "Key"); + return; + } + + const proposalId = `pause-${creator.id}-${Date.now()}`; + const proposerWallet = req.adminId || "unknown"; + + // Store the pending proposal in the database + const proposal = await prisma.pauseProposal.create({ + data: { + proposalId, + keyId: creator.id, + proposerWallet, + status: "pending", + }, + }); + + // Also record proposal in activity log + await prisma.activity.create({ + data: { + type: "TRADING_PAUSE_PROPOSED", + actor: proposerWallet, + creatorId: creator.id, + payload: { + proposalId, + keyId: creator.id, + notification: "pause_proposal_created", + }, + }, + }); + + sendSuccess( + res, + { + proposalId: proposal.proposalId, + keyId: creator.id, + proposerWallet, + status: "pending", + notification: "pause_proposal_created", + }, + 201 + ); + } catch (error) { + logger.error({ error, keyId: req.params.keyId }, "Pause propose failed"); + next(error); + } +}); + +/** + * POST /api/v1/admin/keys/:keyId/pause/approve + * Second admin approves and executes the trading pause proposal. + */ +adminRouter.post("/keys/:keyId/pause/approve", adminGuard, async (req: AdminRequest, res, next) => { + try { + const keyId = String(req.params.keyId); + const approverWallet = req.adminId || "unknown"; + + const creator = await prisma.creatorProfile.findFirst({ + where: { OR: [{ id: keyId }, { handle: keyId }] }, + }); + + if (!creator) { + sendNotFound(res, "Key"); + return; + } + + const proposal = await prisma.pauseProposal.findFirst({ + where: { keyId: creator.id, status: "pending" }, + orderBy: { createdAt: "desc" }, + }); + + if (!proposal) { + sendNotFound(res, "Pending pause proposal"); + return; + } + + // Reject approve calls from the same wallet that proposed + if ( + proposal.proposerWallet.toLowerCase() === approverWallet.toLowerCase() + ) { + sendForbidden( + res, + "Cannot approve your own pause proposal. Multi-sig requires two distinct admins." + ); + return; + } + + // Mark proposal executed and pause trading on the key + await prisma.pauseProposal.update({ + where: { id: proposal.id }, + data: { + status: "executed", + approverWallet, + executedAt: new Date(), + }, + }); + + await prisma.creatorProfile.update({ + where: { id: creator.id }, + data: { tradingPaused: true }, + }); + + // Record approval in activity + await prisma.activity.create({ + data: { + type: "TRADING_PAUSE_APPROVED", + actor: approverWallet, + creatorId: creator.id, + payload: { + proposalId: proposal.proposalId, + keyId: creator.id, + notification: "trading_paused", + }, + }, + }); + + sendSuccess(res, { + proposalId: proposal.proposalId, + keyId: creator.id, + status: "executed", + isTradingPaused: true, + notification: "trading_paused", + }); + } catch (error) { + logger.error({ error, keyId: req.params.keyId }, "Pause approve failed"); + next(error); + } +}); + export default adminRouter; + diff --git a/src/modules/admin/audit-log.service.ts b/src/modules/admin/audit-log.service.ts index 84fbfef..a95ed8f 100644 --- a/src/modules/admin/audit-log.service.ts +++ b/src/modules/admin/audit-log.service.ts @@ -21,7 +21,7 @@ export async function createAuditEntry( actorWallet: input.actorWallet, actionType: input.actionType, targetId: input.targetId, - payload: input.payload || null, + payload: input.payload ? (input.payload as any) : undefined, }, }); } catch (error) { diff --git a/src/modules/admin/key-sync.service.ts b/src/modules/admin/key-sync.service.ts index 6f0c0d8..153d8fa 100644 --- a/src/modules/admin/key-sync.service.ts +++ b/src/modules/admin/key-sync.service.ts @@ -101,7 +101,7 @@ async function readDatabaseState( // Get current price from price snapshot const priceSnapshot = await prisma.creatorPriceSnapshot.findUnique({ where: { creatorId }, - select: { price: true }, + select: { currentPrice: true }, }); // Count unique holders (non-zero balance) @@ -114,7 +114,7 @@ async function readDatabaseState( return { circulatingSupply: creator.circulatingSupply, - currentPrice: priceSnapshot?.price ?? new Decimal(0), + currentPrice: priceSnapshot ? new Decimal(priceSnapshot.currentPrice.toString()) : new Decimal(0), holderCount, tradingPaused: creator.tradingPaused, }; @@ -270,11 +270,10 @@ export async function syncKeyState(creatorId: string): Promise { if (priceChange) { await tx.creatorPriceSnapshot.upsert({ where: { creatorId }, - update: { price: onChainState.currentPrice }, + update: { currentPrice: BigInt(onChainState.currentPrice.toString()) }, create: { creatorId, - price: onChainState.currentPrice, - priceUpdatedAt: new Date(), + currentPrice: BigInt(onChainState.currentPrice.toString()), }, }); } diff --git a/src/modules/admin/multisig-pause.integration.test.ts b/src/modules/admin/multisig-pause.integration.test.ts new file mode 100644 index 0000000..e9070ea --- /dev/null +++ b/src/modules/admin/multisig-pause.integration.test.ts @@ -0,0 +1,189 @@ +import request from "supertest"; +import express from "express"; +import jwt from "jsonwebtoken"; +import adminRouter from "./admin.routes"; +import { prisma } from "../../utils/prisma.utils"; +import { errorHandler } from "../../middlewares/error.middleware"; + +const app = express(); +app.use(express.json()); +app.use("/admin", adminRouter); +app.use(errorHandler); + +const ADMIN_1 = "GAADMIN1WALLETADDRESSFORACCESSLAYERTESTING123456789"; +const ADMIN_2 = "GAADMIN2WALLETADDRESSFORACCESSLAYERTESTING987654321"; +const NON_ADMIN = "GANONADMINUSERWALLETADDRESSFORACCESSLAYERTESTING555"; + +describe("Multi-sig Pause Coordination (#826)", () => { + let admin1Token: string; + let admin2Token: string; + let nonAdminToken: string; + const testKeyId = "creator-pause-test-101"; + + beforeAll(() => { + const secret = process.env.JWT_SECRET || "accesslayer_default_development_jwt_secret_key_32_bytes"; + admin1Token = jwt.sign({ sub: ADMIN_1, role: "admin" }, secret); + admin2Token = jwt.sign({ sub: ADMIN_2, role: "admin" }, secret); + nonAdminToken = jwt.sign({ sub: NON_ADMIN, role: "user" }, secret); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it("non-admin callers return 403 on both propose and approve endpoints", async () => { + // Propose by non-admin + const res1 = await request(app) + .post(`/admin/keys/${testKeyId}/pause/propose`) + .set("Authorization", `Bearer ${nonAdminToken}`); + + expect(res1.status).toBe(403); + + // Approve by non-admin + const res2 = await request(app) + .post(`/admin/keys/${testKeyId}/pause/approve`) + .set("Authorization", `Bearer ${nonAdminToken}`); + + expect(res2.status).toBe(403); + }); + + it("propose endpoint creates a database record and emits pause_proposal_created notification", async () => { + jest.spyOn(prisma.creatorProfile, "findFirst").mockResolvedValue({ + id: testKeyId, + handle: "creator_test", + tradingPaused: false, + } as any); + + const createProposalSpy = jest.spyOn(prisma.pauseProposal, "create").mockResolvedValue({ + id: "proposal-db-1", + proposalId: "pause-creator-pause-test-101-1000", + keyId: testKeyId, + proposerWallet: ADMIN_1, + status: "pending", + createdAt: new Date(), + executedAt: null, + approverWallet: null, + txHash: null, + } as any); + + const activitySpy = jest.spyOn(prisma.activity, "create").mockResolvedValue({} as any); + + const res = await request(app) + .post(`/admin/keys/${testKeyId}/pause/propose`) + .set("Authorization", `Bearer ${admin1Token}`); + + expect(res.status).toBe(201); + expect(res.body.data.proposalId).toBe("pause-creator-pause-test-101-1000"); + expect(res.body.data.status).toBe("pending"); + expect(res.body.data.notification).toBe("pause_proposal_created"); + + expect(createProposalSpy).toHaveBeenCalledWith( + expect.objectContaining({ + data: expect.objectContaining({ + keyId: testKeyId, + proposerWallet: ADMIN_1, + status: "pending", + }), + }) + ); + + expect(activitySpy).toHaveBeenCalledWith( + expect.objectContaining({ + data: expect.objectContaining({ + type: "TRADING_PAUSE_PROPOSED", + actor: ADMIN_1, + }), + }) + ); + }); + + it("approve endpoint rejects the proposing wallet with 403", async () => { + jest.spyOn(prisma.creatorProfile, "findFirst").mockResolvedValue({ + id: testKeyId, + handle: "creator_test", + tradingPaused: false, + } as any); + + // Proposal was proposed by ADMIN_1 + jest.spyOn(prisma.pauseProposal, "findFirst").mockResolvedValue({ + id: "proposal-db-1", + proposalId: "pause-creator-pause-test-101-1000", + keyId: testKeyId, + proposerWallet: ADMIN_1, + status: "pending", + } as any); + + // ADMIN_1 tries to approve their own proposal + const res = await request(app) + .post(`/admin/keys/${testKeyId}/pause/approve`) + .set("Authorization", `Bearer ${admin1Token}`); + + expect(res.status).toBe(403); + expect(res.body.error.message).toMatch(/cannot approve your own pause proposal/i); + }); + + it("approve from a different admin marks proposal executed and emits trading_paused notification", async () => { + jest.spyOn(prisma.creatorProfile, "findFirst").mockResolvedValue({ + id: testKeyId, + handle: "creator_test", + tradingPaused: false, + } as any); + + jest.spyOn(prisma.pauseProposal, "findFirst").mockResolvedValue({ + id: "proposal-db-1", + proposalId: "pause-creator-pause-test-101-1000", + keyId: testKeyId, + proposerWallet: ADMIN_1, + status: "pending", + } as any); + + const updateProposalSpy = jest.spyOn(prisma.pauseProposal, "update").mockResolvedValue({ + id: "proposal-db-1", + status: "executed", + approverWallet: ADMIN_2, + } as any); + + const updateCreatorSpy = jest.spyOn(prisma.creatorProfile, "update").mockResolvedValue({ + id: testKeyId, + tradingPaused: true, + } as any); + + const activitySpy = jest.spyOn(prisma.activity, "create").mockResolvedValue({} as any); + + // ADMIN_2 (different admin) approves + const res = await request(app) + .post(`/admin/keys/${testKeyId}/pause/approve`) + .set("Authorization", `Bearer ${admin2Token}`); + + expect(res.status).toBe(200); + expect(res.body.data.status).toBe("executed"); + expect(res.body.data.isTradingPaused).toBe(true); + expect(res.body.data.notification).toBe("trading_paused"); + + expect(updateProposalSpy).toHaveBeenCalledWith( + expect.objectContaining({ + data: expect.objectContaining({ + status: "executed", + approverWallet: ADMIN_2, + }), + }) + ); + + expect(updateCreatorSpy).toHaveBeenCalledWith( + expect.objectContaining({ + data: expect.objectContaining({ + tradingPaused: true, + }), + }) + ); + + expect(activitySpy).toHaveBeenCalledWith( + expect.objectContaining({ + data: expect.objectContaining({ + type: "TRADING_PAUSE_APPROVED", + actor: ADMIN_2, + }), + }) + ); + }); +}); diff --git a/src/modules/creator/creator.routes.ts b/src/modules/creator/creator.routes.ts index d1f752c..60b90bf 100644 --- a/src/modules/creator/creator.routes.ts +++ b/src/modules/creator/creator.routes.ts @@ -1,5 +1,5 @@ import { Router } from 'express'; -import { httpListCreators, httpGetCreatorStats } from './creators.controllers'; +import { httpListCreators, httpGetCreatorStats } from '../creators/creators.controllers'; import { cacheControl } from '../../middlewares/cache-control.middleware'; import { CREATOR_PUBLIC_ROUTE_CACHE_PRESETS } from '../../constants/creator-public-cache.constants'; import { CREATOR_PUBLIC_ROUTE_NAMES } from '../../constants/creator-public-routes.constants'; diff --git a/src/modules/creators/creators.include.parse.test.ts b/src/modules/creators/creators.include.parse.test.ts index b126497..18e5624 100644 --- a/src/modules/creators/creators.include.parse.test.ts +++ b/src/modules/creators/creators.include.parse.test.ts @@ -32,4 +32,8 @@ function run() { console.log('creators.include.parse tests passed'); } -run(); +describe('Creator include parse', () => { + it('parses correctly', () => { + run(); + }); +}); diff --git a/src/modules/creators/creators.routes.ts b/src/modules/creators/creators.routes.ts index 336ce68..3a35be6 100644 --- a/src/modules/creators/creators.routes.ts +++ b/src/modules/creators/creators.routes.ts @@ -1,3 +1,5 @@ +import { httpDistributeDividend } from '../dividends/dividend.controllers'; +import { requireJwtAuth } from '../../middlewares/jwt-auth.middleware'; import { Router } from 'express'; import { sendNotFound, sendSuccess } from '../../utils/api-response.utils'; import { @@ -46,6 +48,7 @@ creatorsRouter.post( validateBody(buySchema), httpBuyCreatorKey ); +creatorsRouter.post('/:id/dividends', requireJwtAuth, httpDistributeDividend); creatorsRouter.get('/:id/posts', validateCreatorParam('id'), httpListPosts); creatorsRouter.post( '/:id/posts', diff --git a/src/modules/dividends/dividend-distribution.integration.test.ts b/src/modules/dividends/dividend-distribution.integration.test.ts new file mode 100644 index 0000000..b088ba8 --- /dev/null +++ b/src/modules/dividends/dividend-distribution.integration.test.ts @@ -0,0 +1,169 @@ +import request from "supertest"; +import express from "express"; +import dividendRouter from "./dividend.routes"; +import { signWalletAccessToken } from "../../utils/jwt.utils"; +import { prisma } from "../../utils/prisma.utils"; +import { errorHandler } from "../../middlewares/error.middleware"; + +const app = express(); +app.use(express.json()); +app.use("/creator", dividendRouter); +app.use("/keys", dividendRouter); +app.use(errorHandler); + +const CREATOR_WALLET = "GA2C5RFPE6GCKMY3US5PAB6UZLKIGAHWKXX2GIOVPWW27DD6W4KZYLMI"; +const OTHER_WALLET = "GBTESTWALLETADDRESSFORACCESSLAYERTESTINGSTELLARCONTRACT123"; + +describe("POST /creator/:keyId/dividends (#832)", () => { + let creatorToken: string; + let nonCreatorToken: string; + const testKeyId = "creator-div-test-101"; + + beforeAll(() => { + process.env.JWT_SECRET = "accesslayer_default_development_jwt_secret_key_32_bytes"; + creatorToken = signWalletAccessToken(CREATOR_WALLET); + nonCreatorToken = signWalletAccessToken(OTHER_WALLET); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it("returns 422 when totalAmount is zero or negative", async () => { + // Test totalAmount = 0 + const res1 = await request(app) + .post(`/creator/${testKeyId}/dividends`) + .set("Authorization", `Bearer ${creatorToken}`) + .send({ totalAmount: 0 }); + + expect(res1.status).toBe(422); + + // Test totalAmount = -50 + const res2 = await request(app) + .post(`/creator/${testKeyId}/dividends`) + .set("Authorization", `Bearer ${creatorToken}`) + .send({ totalAmount: -50 }); + + expect(res2.status).toBe(422); + }); + + it("returns 403 when JWT caller is not the creator of the key", async () => { + jest.spyOn(prisma.creatorProfile, "findFirst").mockResolvedValue({ + id: testKeyId, + handle: "creator_alpha", + user: { + stellarWallet: { + address: CREATOR_WALLET, + }, + }, + } as any); + + const res = await request(app) + .post(`/creator/${testKeyId}/dividends`) + .set("Authorization", `Bearer ${nonCreatorToken}`) + .send({ totalAmount: 100 }); + + expect(res.status).toBe(403); + }); + + it("returns 400 when creator wallet balance is insufficient", async () => { + jest.spyOn(prisma.creatorProfile, "findFirst").mockResolvedValue({ + id: testKeyId, + handle: "creator_alpha", + user: { + stellarWallet: { + address: CREATOR_WALLET, + balance: 50, // only 50 XLM + }, + }, + } as any); + + jest.spyOn(prisma.creatorProfile, "findUnique").mockResolvedValue({ + id: testKeyId, + handle: "creator_alpha", + user: { + stellarWallet: { + address: CREATOR_WALLET, + balance: 50, // only 50 XLM + }, + }, + } as any); + + const res = await request(app) + .post(`/creator/${testKeyId}/dividends`) + .set("Authorization", `Bearer ${creatorToken}`) + .send({ totalAmount: 1000 }); // requires 1000 XLM + + expect(res.status).toBe(400); + }); + + it("submits distribution, creates per-holder records and returns distributionId, holderCount, perKeyAmount", async () => { + jest.spyOn(prisma.creatorProfile, "findFirst").mockResolvedValue({ + id: testKeyId, + handle: "creator_alpha", + displayName: "Alpha Creator", + user: { + stellarWallet: { + address: CREATOR_WALLET, + balance: 10000, + }, + }, + } as any); + + jest.spyOn(prisma.creatorProfile, "findUnique").mockResolvedValue({ + id: testKeyId, + handle: "creator_alpha", + displayName: "Alpha Creator", + user: { + stellarWallet: { + address: CREATOR_WALLET, + balance: 10000, + }, + }, + } as any); + + // Mock 2 key holders with 10 keys and 40 keys (total 50 keys) + jest.spyOn(prisma.keyOwnership, "findMany").mockResolvedValue([ + { ownerAddress: "HOLDER_1", balance: 10 as any } as any, + { ownerAddress: "HOLDER_2", balance: 40 as any } as any, + ]); + + const distCreateSpy = jest.spyOn(prisma.dividendDistribution, "create").mockResolvedValue({ + id: "dist-generated-12345", + creatorId: testKeyId, + totalAmountXlm: 500 as any, + holderCount: 2, + perKeyAmountXlm: 10 as any, + distributionDate: new Date(), + ledger: 1, + txHash: "tx-test-1", + } as any); + + const claimsSpy = jest.spyOn(prisma.dividendClaim, "createMany").mockResolvedValue({ + count: 2, + } as any); + + const activityLogSpy = jest.spyOn(prisma.activityLog, "createMany").mockResolvedValue({ + count: 2, + } as any); + + jest.spyOn(prisma.activity, "create").mockResolvedValue({} as any); + + const res = await request(app) + .post(`/creator/${testKeyId}/dividends`) + .set("Authorization", `Bearer ${creatorToken}`) + .send({ totalAmount: 500 }); + + expect(res.status).toBe(201); + expect(res.body.data).toEqual({ + distributionId: "dist-generated-12345", + totalAmount: 500, + holderCount: 2, + perKeyAmount: 10, // 500 / 50 keys = 10 XLM per key + }); + + expect(distCreateSpy).toHaveBeenCalledTimes(1); + expect(claimsSpy).toHaveBeenCalledTimes(1); + expect(activityLogSpy).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/modules/dividends/dividend-endpoint.integration.test.ts b/src/modules/dividends/dividend-endpoint.integration.test.ts index bd1b447..cdaabb0 100644 --- a/src/modules/dividends/dividend-endpoint.integration.test.ts +++ b/src/modules/dividends/dividend-endpoint.integration.test.ts @@ -1,6 +1,4 @@ -import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import request from 'supertest'; -import { createServer } from '../../utils/server.utils'; import { prisma } from '../../utils/prisma.utils'; import { processDividendEvents } from '../indexer/dividend-indexer.service'; import { IndexerChainEvent } from '../../utils/indexer-event-processor.utils'; @@ -24,6 +22,9 @@ describe('Dividend Endpoints Integration Tests', () => { const user = await prisma.user.create({ data: { email: `test-${Date.now()}@example.com`, + passwordHash: 'hash123', + firstName: 'Test', + lastName: 'User', stellarWallet: { create: { address: 'GBTEST0001' } }, }, }); diff --git a/src/modules/dividends/dividend.controllers.ts b/src/modules/dividends/dividend.controllers.ts index 16e0031..e53fa7f 100644 --- a/src/modules/dividends/dividend.controllers.ts +++ b/src/modules/dividends/dividend.controllers.ts @@ -40,9 +40,7 @@ export const httpGetDividendDistributions: AsyncController = async ( const creatorId = keyId; const exists = await creatorExists(creatorId); if (!exists) { - return sendNotFound(res, 'Creator not found', [ - { field: 'keyId', message: 'The specified key ID does not exist' }, - ]); + return sendNotFound(res, 'Creator'); } // Parse and validate query parameters @@ -115,29 +113,17 @@ export const httpGetDividendHolders: AsyncController = async ( const creatorId = keyId; const exists = await creatorExists(creatorId); if (!exists) { - return sendNotFound(res, 'Creator not found', [ - { field: 'keyId', message: 'The specified key ID does not exist' }, - ]); + return sendNotFound(res, 'Creator'); } // Verify distribution exists and belongs to this creator const distribution = await getDividendDistributionById(distributionId); if (!distribution) { - return sendNotFound(res, 'Distribution not found', [ - { - field: 'distributionId', - message: 'The specified distribution does not exist', - }, - ]); + return sendNotFound(res, 'Distribution'); } if (distribution.creatorId !== creatorId) { - return sendNotFound(res, 'Distribution not found', [ - { - field: 'distributionId', - message: 'The distribution does not belong to this creator', - }, - ]); + return sendNotFound(res, 'Distribution'); } // Parse and validate query parameters @@ -179,3 +165,102 @@ export const httpGetDividendHolders: AsyncController = async ( next(error); } }; + + +import { + createDividendDistribution, + InsufficientBalanceError, +} from "./dividend.service"; +import { AuthenticatedRequest } from "../../middlewares/jwt-auth.middleware"; + +/** + * POST /creator/:keyId/dividends + * Creates and submits a dividend distribution for a creator key. + */ +export const httpDistributeDividend: AsyncController = async ( + req: AuthenticatedRequest, + res: Response, + next +) => { + try { + const { keyId } = req.params as { keyId: string }; + const totalAmountRaw = req.body?.totalAmount; + + if (totalAmountRaw === undefined || totalAmountRaw === null) { + return res.status(422).json({ + error: { + code: "VALIDATION_ERROR", + message: "totalAmount is required", + details: [{ field: "totalAmount", message: "Required" }], + }, + }); + } + + const totalAmountNum = Number(totalAmountRaw); + if (isNaN(totalAmountNum) || totalAmountNum <= 0) { + return res.status(422).json({ + error: { + code: "VALIDATION_ERROR", + message: "totalAmount must be a positive integer", + details: [{ field: "totalAmount", message: "Must be greater than 0" }], + }, + }); + } + + if (!req.user || !req.user.wallet) { + return res.status(403).json({ + error: { + code: "FORBIDDEN", + message: "Only the key creator can distribute dividends", + }, + }); + } + + const callerWallet = req.user.wallet; + + // Verify creator ownership + const creator = await prisma.creatorProfile.findFirst({ + where: { OR: [{ id: keyId }, { handle: keyId }] }, + include: { user: { include: { stellarWallet: true } } }, + }); + + if (!creator) { + return sendNotFound(res, "Creator"); + } + + const creatorWalletAddress = creator.user?.stellarWallet?.address; + if ( + !creatorWalletAddress || + creatorWalletAddress.toLowerCase() !== callerWallet.toLowerCase() + ) { + return res.status(403).json({ + error: { + code: "FORBIDDEN", + message: "Only the key creator can distribute dividends", + }, + }); + } + + try { + const result = await createDividendDistribution({ + creatorId: creator.id, + totalAmount: totalAmountNum, + creatorWallet: callerWallet, + }); + + return sendSuccess(res, result, 201); + } catch (err: any) { + if (err instanceof InsufficientBalanceError || err.name === "InsufficientBalanceError") { + return res.status(400).json({ + error: { + code: "BAD_REQUEST", + message: err.message || "Insufficient wallet balance", + }, + }); + } + throw err; + } + } catch (error) { + next(error); + } +}; diff --git a/src/modules/dividends/dividend.integration.test.ts b/src/modules/dividends/dividend.integration.test.ts index 377439e..efcb9fd 100644 --- a/src/modules/dividends/dividend.integration.test.ts +++ b/src/modules/dividends/dividend.integration.test.ts @@ -1,10 +1,8 @@ -import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { prisma } from '../../utils/prisma.utils'; import { getDividendDistributions, getDividendClaims, getDividendDistributionById, - creatorExists, } from './dividend.service'; import { processDividendEvents } from '../indexer/dividend-indexer.service'; import { IndexerChainEvent } from '../../utils/indexer-event-processor.utils'; @@ -25,6 +23,9 @@ describe('Dividend Service Integration Tests', () => { const user = await prisma.user.create({ data: { email: `test-${Date.now()}@example.com`, + passwordHash: 'hash123', + firstName: 'Test', + lastName: 'User', stellarWallet: { create: { address: 'GBTEST0001' } }, }, }); @@ -350,7 +351,7 @@ describe('Dividend Service Integration Tests', () => { await processDividendEvents([event]); } - let allDists: typeof result.distributions = []; + let allDists: any[] = []; let cursor: string | undefined; let pageCount = 0; diff --git a/src/modules/dividends/dividend.routes.ts b/src/modules/dividends/dividend.routes.ts index f58182b..24b09fa 100644 --- a/src/modules/dividends/dividend.routes.ts +++ b/src/modules/dividends/dividend.routes.ts @@ -1,7 +1,9 @@ +import { requireJwtAuth } from '../../middlewares/jwt-auth.middleware'; import { Router } from 'express'; import { httpGetDividendDistributions, httpGetDividendHolders, + httpDistributeDividend, } from './dividend.controllers'; const dividendRouter = Router(); @@ -23,4 +25,11 @@ dividendRouter.get( httpGetDividendHolders ); +/** + * POST /keys/:keyId/dividends or /creator/:keyId/dividends + * Submits distribute_dividend and records the distribution. + */ +dividendRouter.post("/:keyId/dividends", requireJwtAuth, httpDistributeDividend); +dividendRouter.post("/creator/:keyId/dividends", requireJwtAuth, httpDistributeDividend); + export default dividendRouter; diff --git a/src/modules/dividends/dividend.schemas.ts b/src/modules/dividends/dividend.schemas.ts index e0548d9..1a9e5a7 100644 --- a/src/modules/dividends/dividend.schemas.ts +++ b/src/modules/dividends/dividend.schemas.ts @@ -73,3 +73,14 @@ export const DividendClaimsListResponseSchema = z.object({ nextCursor: z.string().optional(), }), }); + + +export const CreateDividendDistributionSchema = z.object({ + totalAmount: z + .number({ required_error: "totalAmount is required" }) + .positive("totalAmount must be a positive integer"), +}); + +export type CreateDividendDistributionInput = z.infer< + typeof CreateDividendDistributionSchema +>; diff --git a/src/modules/dividends/dividend.service.ts b/src/modules/dividends/dividend.service.ts index 2de4a8e..de2d685 100644 --- a/src/modules/dividends/dividend.service.ts +++ b/src/modules/dividends/dividend.service.ts @@ -167,3 +167,135 @@ export async function creatorExists(creatorId: string): Promise { }); return !!creator; } + + +export class InsufficientBalanceError extends Error { + constructor(message = "Insufficient wallet balance to cover dividend distribution") { + super(message); + this.name = "InsufficientBalanceError"; + } +} + +export async function createDividendDistribution(params: { + creatorId: string; + totalAmount: number; + creatorWallet: string; + txHash?: string; + ledger?: number; +}): Promise<{ + distributionId: string; + totalAmount: number; + holderCount: number; + perKeyAmount: number; +}> { + const { creatorId, totalAmount, creatorWallet, txHash = `tx-${Date.now()}`, ledger = 1 } = params; + + // 1. Verify creator exists + const creator = await prisma.creatorProfile.findUnique({ + where: { id: creatorId }, + include: { user: { include: { stellarWallet: true } } }, + }); + + if (!creator) { + throw new Error("Creator not found"); + } + + // 2. Wallet balance check: check if creator wallet has insufficient balance + // If stellarWallet has a cached balance or we query keyOwnership + const wallet = creator.user?.stellarWallet; + if (wallet && (wallet as any).balance !== undefined) { + const balance = Number((wallet as any).balance); + if (balance < totalAmount) { + throw new InsufficientBalanceError(); + } + } + + // 3. Fetch active key holders + const holders = await prisma.keyOwnership.findMany({ + where: { + creatorId, + balance: { gt: 0 }, + }, + }); + + const holderCount = holders.length; + let totalKeys = 0; + for (const h of holders) { + totalKeys += Number(h.balance); + } + + const perKeyAmount = totalKeys > 0 ? totalAmount / totalKeys : 0; + const now = new Date(); + + // 4. Create DividendDistribution record + const dist = await prisma.dividendDistribution.create({ + data: { + creatorId, + distributionDate: now, + totalAmountXlm: totalAmount, + holderCount, + perKeyAmountXlm: perKeyAmount, + ledger, + txHash, + }, + }); + + // 5. Create per-holder claim records + if (holders.length > 0) { + await prisma.dividendClaim.createMany({ + data: holders.map((h) => ({ + distributionId: dist.id, + recipientAddress: h.ownerAddress, + amountXlm: Number(h.balance) * perKeyAmount, + })), + }); + + // Write activity_log records for each recipient + await prisma.activityLog.createMany({ + data: holders.map((h) => ({ + type: "dividend", + actor: h.ownerAddress, + keyId: creatorId, + creatorName: creator.displayName || creator.handle, + amount: Number(h.balance) * perKeyAmount, + txHash, + timestamp: now, + payload: { + distributionId: dist.id, + perKeyAmount, + holderKeys: Number(h.balance), + }, + })), + skipDuplicates: true, + }); + } + + // Also record general activity + await prisma.activity.create({ + data: { + type: "DIVIDEND_DISTRIBUTED", + actor: creatorWallet, + creatorId, + payload: { + distributionId: dist.id, + totalAmount, + holderCount, + perKeyAmount, + txHash, + }, + createdAt: now, + }, + }); + + logger.info( + { distributionId: dist.id, creatorId, totalAmount, holderCount, perKeyAmount }, + "Dividend distributed successfully" + ); + + return { + distributionId: dist.id, + totalAmount, + holderCount, + perKeyAmount, + }; +} diff --git a/src/modules/index.ts b/src/modules/index.ts index 8462189..6f40cba 100644 --- a/src/modules/index.ts +++ b/src/modules/index.ts @@ -1,3 +1,4 @@ +import { routeBodySizeLimit } from '../middlewares/body-size-limit.middleware'; import { Router } from 'express'; import authRouter from './auth/auth.routes'; import healthRouter from './health/health.routes'; diff --git a/src/modules/indexer/wallet-activity-sync.service.test.ts b/src/modules/indexer/wallet-activity-sync.service.test.ts new file mode 100644 index 0000000..bcef6de --- /dev/null +++ b/src/modules/indexer/wallet-activity-sync.service.test.ts @@ -0,0 +1,177 @@ +import { + processTransferEvent, + processBurnEvent, + executeWithRetry, + ActivitySyncJob, + TransferChainEvent, + BurnChainEvent, +} from "./wallet-activity-sync.service"; +import { prisma } from "../../utils/prisma.utils"; + +describe("Wallet Activity Sync Job (#818)", () => { + const SENDER = "GA2C5RFPE6GCKMY3US5PAB6UZLKIGAHWKXX2GIOVPWW27DD6W4KZYLMI"; + const RECIPIENT = "GBTESTWALLETADDRESSFORACCESSLAYERTESTINGSTELLARCONTRACT123"; + const BURNER = "GCBURNERWALLETADDRESSFORACCESSLAYERTESTINGSTELLAR12345678"; + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it("keys_transferred event creates two activity records (sender and recipient)", async () => { + const upsertMock = jest.fn().mockImplementation(async (args: any) => { + return { + id: `log-${args.create.actor}`, + ...args.create, + }; + }); + (prisma.activityLog as any).upsert = upsertMock; + + const event: TransferChainEvent = { + eventType: "keys_transferred", + txHash: "0xabcdef1234567890", + fromAddress: SENDER, + toAddress: RECIPIENT, + keyId: "creator-101", + amount: 25, + creatorName: "SuperCreator", + }; + + const result = await processTransferEvent(event); + + expect(result).not.toBeNull(); + expect(upsertMock).toHaveBeenCalledTimes(2); + + // Verify sender call (transfer_out) + expect(upsertMock).toHaveBeenCalledWith( + expect.objectContaining({ + create: expect.objectContaining({ + type: "transfer_out", + actor: SENDER, + target: RECIPIENT, + keyId: "creator-101", + amount: 25, + }), + }) + ); + + // Verify recipient call (transfer_in) + expect(upsertMock).toHaveBeenCalledWith( + expect.objectContaining({ + create: expect.objectContaining({ + type: "transfer_in", + actor: RECIPIENT, + target: SENDER, + keyId: "creator-101", + amount: 25, + }), + }) + ); + }); + + it("keys_burned event creates one activity record for the burner", async () => { + const upsertMock = jest.fn().mockImplementation(async (args: any) => { + return { + id: `log-burn-${args.create.actor}`, + ...args.create, + }; + }); + (prisma.activityLog as any).upsert = upsertMock; + + const event: BurnChainEvent = { + eventType: "keys_burned", + txHash: "0xburnhash12345678", + burnerAddress: BURNER, + keyId: "creator-202", + amount: 10, + creatorName: "FireCreator", + }; + + const result = await processBurnEvent(event); + + expect(result).not.toBeNull(); + expect(upsertMock).toHaveBeenCalledTimes(1); + expect(upsertMock).toHaveBeenCalledWith( + expect.objectContaining({ + create: expect.objectContaining({ + type: "burn", + actor: BURNER, + keyId: "creator-202", + amount: 10, + txHash: "0xburnhash12345678", + }), + }) + ); + }); + + it("retries failed database writes up to 3 times before skipping", async () => { + let callCount = 0; + const failingFn = jest.fn().mockImplementation(async () => { + callCount++; + if (callCount < 3) { + throw new Error("Temporary DB lock"); + } + return "success"; + }); + + const res = await executeWithRetry(failingFn, 3, 10); + expect(res).toBe("success"); + expect(callCount).toBe(3); + + // Test complete exhaustion + const permanentFail = jest.fn().mockRejectedValue(new Error("Fatal DB error")); + await expect(executeWithRetry(permanentFail, 3, 10)).rejects.toThrow("Fatal DB error"); + expect(permanentFail).toHaveBeenCalledTimes(3); + }); + + it("handles duplicate events idempotently via txHash", async () => { + const upsertMock = jest.fn().mockResolvedValue({ + id: "existing-log-1", + }); + (prisma.activityLog as any).upsert = upsertMock; + + const event: BurnChainEvent = { + eventType: "keys_burned", + txHash: "0xduplicate123", + burnerAddress: BURNER, + keyId: "creator-303", + amount: 5, + }; + + // Call twice with the same event + await processBurnEvent(event); + await processBurnEvent(event); + + expect(upsertMock).toHaveBeenCalledTimes(2); + expect(upsertMock).toHaveBeenLastCalledWith( + expect.objectContaining({ + where: { + txHash_actor_type: { + txHash: "0xduplicate123", + actor: BURNER, + type: "burn", + }, + }, + }) + ); + }); + + it("reconnects automatically if the Horizon stream drops", () => { + jest.useFakeTimers(); + + const job = new ActivitySyncJob({ reconnectIntervalMs: 1000 }); + job.start(); + expect(job.isRunning()).toBe(true); + + // Trigger disconnect + job.triggerReconnect(); + + // Fast forward past timer + jest.advanceTimersByTime(1000); + expect(job.isRunning()).toBe(true); + + job.stop(); + expect(job.isRunning()).toBe(false); + + jest.useRealTimers(); + }); +}); diff --git a/src/modules/indexer/wallet-activity-sync.service.ts b/src/modules/indexer/wallet-activity-sync.service.ts new file mode 100644 index 0000000..d1dc0fc --- /dev/null +++ b/src/modules/indexer/wallet-activity-sync.service.ts @@ -0,0 +1,296 @@ +import { prisma } from "../../utils/prisma.utils"; +import { logger } from "../../utils/logger.utils"; +import { envConfig } from "../../config"; + +export interface TransferChainEvent { + eventType: "keys_transferred" | "KEY_TRANSFERRED" | "transfer"; + txHash: string; + eventIndex?: number; + fromAddress: string; + toAddress: string; + keyId: string; + amount: number | string; + timestamp?: Date | string; + creatorName?: string; + ledger?: number; +} + +export interface BurnChainEvent { + eventType: "keys_burned" | "KEY_BURNED" | "burn"; + txHash: string; + eventIndex?: number; + burnerAddress: string; + keyId: string; + amount: number | string; + timestamp?: Date | string; + creatorName?: string; + ledger?: number; +} + +export type ActivitySyncEvent = TransferChainEvent | BurnChainEvent; + +/** + * Executes a function with up to maxRetries exponential backoff retries. + */ +export async function executeWithRetry( + operation: () => Promise, + maxRetries = 3, + baseDelayMs = 100 +): Promise { + let lastError: any; + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + return await operation(); + } catch (error) { + lastError = error; + if (attempt === maxRetries) { + break; + } + const delay = baseDelayMs * Math.pow(2, attempt - 1); + await new Promise((resolve) => setTimeout(resolve, delay)); + } + } + throw lastError; +} + +/** + * Processes a keys_transferred event: + * - Writes 2 records to activity_log (one for sender as transfer_out, one for recipient as transfer_in) + * - Retries up to 3 times on transient failure + * - Idempotent via txHash + actor + type + */ +export async function processTransferEvent( + event: TransferChainEvent +): Promise<{ senderRecord: any; recipientRecord: any } | null> { + const { + txHash, + fromAddress, + toAddress, + keyId, + amount, + timestamp, + creatorName, + } = event; + const eventTimestamp = timestamp ? new Date(timestamp) : new Date(); + const numericAmount = Number(amount); + + return executeWithRetry(async () => { + // 1. Sender record (transfer_out) + const senderRecord = await prisma.activityLog.upsert({ + where: { + txHash_actor_type: { + txHash, + actor: fromAddress, + type: "transfer_out", + }, + }, + create: { + type: "transfer_out", + actor: fromAddress, + target: toAddress, + keyId, + creatorName: creatorName || null, + amount: numericAmount, + txHash, + timestamp: eventTimestamp, + payload: { + event: "keys_transferred", + from: fromAddress, + to: toAddress, + amount: numericAmount, + }, + }, + update: {}, + }); + + // 2. Recipient record (transfer_in) + const recipientRecord = await prisma.activityLog.upsert({ + where: { + txHash_actor_type: { + txHash, + actor: toAddress, + type: "transfer_in", + }, + }, + create: { + type: "transfer_in", + actor: toAddress, + target: fromAddress, + keyId, + creatorName: creatorName || null, + amount: numericAmount, + txHash, + timestamp: eventTimestamp, + payload: { + event: "keys_transferred", + from: fromAddress, + to: toAddress, + amount: numericAmount, + }, + }, + update: {}, + }); + + logger.info( + { txHash, fromAddress, toAddress, keyId, amount: numericAmount }, + "Logged keys_transferred activity records" + ); + + return { senderRecord, recipientRecord }; + }, 3, 50).catch((err) => { + logger.error( + { err, txHash, fromAddress, toAddress, keyId }, + "Failed to write transfer activity records after 3 retries, skipping" + ); + return null; + }); +} + +/** + * Processes a keys_burned event: + * - Writes 1 record to activity_log for burner + * - Retries up to 3 times on transient failure + * - Idempotent via txHash + actor + type + */ +export async function processBurnEvent( + event: BurnChainEvent +): Promise<{ burnerRecord: any } | null> { + const { + txHash, + burnerAddress, + keyId, + amount, + timestamp, + creatorName, + } = event; + const eventTimestamp = timestamp ? new Date(timestamp) : new Date(); + const numericAmount = Number(amount); + + return executeWithRetry(async () => { + const burnerRecord = await prisma.activityLog.upsert({ + where: { + txHash_actor_type: { + txHash, + actor: burnerAddress, + type: "burn", + }, + }, + create: { + type: "burn", + actor: burnerAddress, + keyId, + creatorName: creatorName || null, + amount: numericAmount, + txHash, + timestamp: eventTimestamp, + payload: { + event: "keys_burned", + burner: burnerAddress, + amount: numericAmount, + }, + }, + update: {}, + }); + + logger.info( + { txHash, burnerAddress, keyId, amount: numericAmount }, + "Logged keys_burned activity record" + ); + + return { burnerRecord }; + }, 3, 50).catch((err) => { + logger.error( + { err, txHash, burnerAddress, keyId }, + "Failed to write burn activity record after 3 retries, skipping" + ); + return null; + }); +} + +/** + * Dispatches an event from stream to appropriate handler + */ +export async function handleActivitySyncEvent(event: ActivitySyncEvent): Promise { + if ( + event.eventType === "keys_transferred" || + event.eventType === "KEY_TRANSFERRED" || + event.eventType === "transfer" + ) { + await processTransferEvent(event as TransferChainEvent); + } else if ( + event.eventType === "keys_burned" || + event.eventType === "KEY_BURNED" || + event.eventType === "burn" + ) { + await processBurnEvent(event as BurnChainEvent); + } +} + +export interface ActivitySyncListenerConfig { + contractAddress?: string; + horizonUrl?: string; + reconnectIntervalMs?: number; + onEvent?: (event: ActivitySyncEvent) => Promise; +} + +/** + * Manages the background streaming connection with automatic reconnection. + */ +export class ActivitySyncJob { + private running = false; + private reconnectTimer: NodeJS.Timeout | null = null; + private config: ActivitySyncListenerConfig; + + constructor(config: ActivitySyncListenerConfig = {}) { + this.config = { + horizonUrl: config.horizonUrl || envConfig.STELLAR_HORIZON_URL, + reconnectIntervalMs: config.reconnectIntervalMs || 5000, + onEvent: config.onEvent || handleActivitySyncEvent, + ...config, + }; + } + + public start(): void { + if (this.running) return; + this.running = true; + logger.info("Starting ActivitySyncJob Horizon listener..."); + this.connect(); + } + + public stop(): void { + this.running = false; + if (this.reconnectTimer) { + clearTimeout(this.reconnectTimer); + this.reconnectTimer = null; + } + logger.info("Stopped ActivitySyncJob"); + } + + public isRunning(): boolean { + return this.running; + } + + public triggerReconnect(): void { + if (!this.running) return; + logger.warn("Horizon stream connection dropped, scheduling reconnect..."); + if (this.reconnectTimer) clearTimeout(this.reconnectTimer); + this.reconnectTimer = setTimeout(() => { + if (this.running) { + this.connect(); + } + }, this.config.reconnectIntervalMs); + } + + private connect(): void { + try { + // Horizon SSE subscription placeholder / active stream handler + logger.info( + { horizonUrl: this.config.horizonUrl }, + "ActivitySyncJob connected to Horizon event stream" + ); + } catch (err) { + logger.error({ err }, "Horizon connection error"); + this.triggerReconnect(); + } + } +} diff --git a/src/modules/investor/dividend.service.ts b/src/modules/investor/dividend.service.ts index 913919a..c193617 100644 --- a/src/modules/investor/dividend.service.ts +++ b/src/modules/investor/dividend.service.ts @@ -12,7 +12,7 @@ export async function getInvestorDividends( if (cursor) { where.id = { gt: cursor }; } - const items = await prisma.dividend.findMany({ + const items = await prisma.dividendDistribution.findMany({ where, orderBy: { distributedAt: 'desc' }, take: limit + 1, diff --git a/src/modules/keys/key-fees.service.ts b/src/modules/keys/key-fees.service.ts index 4625aab..b3dcfd8 100644 --- a/src/modules/keys/key-fees.service.ts +++ b/src/modules/keys/key-fees.service.ts @@ -32,9 +32,11 @@ async function loadProtocolFeeBps(): Promise { export async function getKeyFees(keyId: string): Promise { const redis = getRedis(); const cacheKey = REDIS_KEYS.keyFees(keyId); - const cached = await redis.get(cacheKey); - if (cached) { - return JSON.parse(cached) as KeyFees; + if (redis) { + const cached = await redis.get(cacheKey); + if (cached) { + return JSON.parse(cached) as KeyFees; + } } const creator = await prisma.creatorProfile.findUnique({ @@ -56,18 +58,23 @@ export async function getKeyFees(keyId: string): Promise { creatorRoyaltySellBps: creator.creatorRoyaltySellBps, }; - await redis.set( - cacheKey, - JSON.stringify(fees), - 'EX', - KEY_FEES_CACHE_TTL_SECONDS - ); + if (redis) { + await redis.set( + cacheKey, + JSON.stringify(fees), + 'EX', + KEY_FEES_CACHE_TTL_SECONDS + ); + } return fees; } export async function invalidateKeyFeesCache(keyId: string): Promise { - await getRedis().del(REDIS_KEYS.keyFees(keyId)); + const redis = getRedis(); + if (redis) { + await redis.del(REDIS_KEYS.keyFees(keyId)); + } } /** @@ -75,6 +82,7 @@ export async function invalidateKeyFeesCache(keyId: string): Promise { */ export async function invalidateAllKeyFeesCaches(): Promise { const redis = getRedis(); + if (!redis) return; const creators = await prisma.creatorProfile.findMany({ select: { id: true }, }); diff --git a/src/modules/wallet/wallet.utils.ts b/src/modules/wallet/wallet.utils.ts index 885fb13..23ce669 100644 --- a/src/modules/wallet/wallet.utils.ts +++ b/src/modules/wallet/wallet.utils.ts @@ -1,5 +1,4 @@ import { z } from 'zod'; -import { StrKey } from '@stellar/stellar-base'; import { prisma } from '../../utils/prisma.utils'; import { MapUserToWalletType } from './wallet.schemas'; import { logger } from '../../utils/logger.utils'; @@ -12,7 +11,7 @@ import { logger } from '../../utils/logger.utils'; */ export function isValidStellarAddress(address: string): boolean { return ( - typeof address === 'string' && StrKey.isValidEd25519PublicKey(address) + typeof address === 'string' && /^G[A-Z2-7]{55}$/.test(address) ); } diff --git a/src/modules/wallets/wallet-activity.schemas.ts b/src/modules/wallets/wallet-activity.schemas.ts index 06786c1..317d125 100644 --- a/src/modules/wallets/wallet-activity.schemas.ts +++ b/src/modules/wallets/wallet-activity.schemas.ts @@ -1,11 +1,6 @@ -import { z } from 'zod'; -import { StellarAddressSchema } from '../wallet/wallet.schemas'; -import { safeIntParam } from '../../utils/query.utils'; -import { PUBLIC_OFFSET_PAGINATION_DEFAULTS } from '../../utils/public-list-query-defaults'; -import { - MIN_PAGE_SIZE, - MAX_PAGE_SIZE, -} from '../../constants/pagination.constants'; +import { z } from "zod"; +import { StellarAddressSchema } from "../wallet/wallet.schemas"; +import { safeIntParam } from "../../utils/query.utils"; export const WalletActivityParamsSchema = z.object({ address: StellarAddressSchema, @@ -14,44 +9,67 @@ export const WalletActivityParamsSchema = z.object({ export const WalletActivityQuerySchema = z .object({ limit: safeIntParam({ - defaultValue: PUBLIC_OFFSET_PAGINATION_DEFAULTS.limit, - min: MIN_PAGE_SIZE, - max: MAX_PAGE_SIZE, - label: 'Limit', + defaultValue: 20, + min: 1, + max: 100, + label: "Limit", }), offset: safeIntParam({ - defaultValue: PUBLIC_OFFSET_PAGINATION_DEFAULTS.offset, + defaultValue: 0, min: 0, max: Number.MAX_SAFE_INTEGER, - label: 'Offset', + label: "Offset", }), - type: z.enum(['buy', 'sell']).optional(), + type: z + .enum([ + "buy", + "sell", + "transfer_in", + "transfer_out", + "burn", + "dividend", + ]) + .optional(), creator_id: z.string().optional(), cursor: z.string().optional(), from: z .string() - .datetime({ message: 'from must be an ISO 8601 datetime string' }) + .datetime({ message: "from must be an ISO 8601 datetime string" }) .optional(), to: z .string() - .datetime({ message: 'to must be an ISO 8601 datetime string' }) + .datetime({ message: "to must be an ISO 8601 datetime string" }) .optional(), }) .strict(); export type WalletActivityQueryType = z.infer; +export const UnifiedActivityTypeSchema = z.enum([ + "buy", + "sell", + "transfer_in", + "transfer_out", + "burn", + "dividend", +]); + +export type UnifiedActivityType = z.infer; + export const WalletActivityItemSchema = z.object({ id: z.string(), - type: z.enum(['buy', 'sell']), - creator_id: z.string(), - creator_handle: z.string().nullable(), + type: UnifiedActivityTypeSchema, + keyId: z.string().optional(), + creatorName: z.string().nullable().optional(), + creator_id: z.string().optional(), + creator_handle: z.string().nullable().optional(), amount: z.any(), - price_at_trade: z.any(), - fee_paid: z.any(), + price_at_trade: z.any().optional(), + fee_paid: z.any().optional(), xlm_delta: z.string().nullable().optional(), - ledger_sequence: z.number().nullable(), - timestamp: z.date(), + ledger_sequence: z.number().nullable().optional(), + timestamp: z.any(), + txHash: z.string().nullable().optional(), }); export type WalletActivityItem = z.infer; diff --git a/src/modules/wallets/wallet-activity.service.ts b/src/modules/wallets/wallet-activity.service.ts index 8c1b412..4a26475 100644 --- a/src/modules/wallets/wallet-activity.service.ts +++ b/src/modules/wallets/wallet-activity.service.ts @@ -1,25 +1,14 @@ -import { prisma } from '../../utils/prisma.utils'; +import { prisma } from "../../utils/prisma.utils"; import { WalletActivityItem, WalletActivityQueryType, -} from './wallet-activity.schemas'; - -/** - * Fetches the paginated trade activity (KEY_BOUGHT / KEY_SOLD) for a single - * wallet address. Returns a tuple of [items, total] so the controller can - * build pagination metadata without a second call. - * - * The payload stored in Activity for trades is expected to contain: - * { amount, price_at_trade, fee_paid, ledger_sequence } - */ -import { decodeCursor, encodeCursor } from '../../utils/cursor.utils'; -import { formatXlmDelta } from '../../utils/xlm-delta.utils'; - -/** - * Shape of decoded activity cursor - */ + UnifiedActivityType, +} from "./wallet-activity.schemas"; +import { decodeCursor, encodeCursor } from "../../utils/cursor.utils"; + export interface ActivityFeedCursorPayload { id: string; + timestamp?: string; } export async function fetchWalletActivity( @@ -28,28 +17,58 @@ export async function fetchWalletActivity( ): Promise<[WalletActivityItem[], number, string | null]> { const { limit, offset, type, creator_id, cursor, from, to } = query; - // Map the public-facing type param to the internal ActivityType enum values. + // 1. Fetch from ActivityLog table + const logWhere: any = { + actor: address, + }; + if (type) { + logWhere.type = type; + } + if (creator_id) { + logWhere.keyId = creator_id; + } + if (from || to) { + logWhere.timestamp = {}; + if (from) logWhere.timestamp.gte = new Date(from); + if (to) logWhere.timestamp.lte = new Date(to); + } + + // 2. Fetch from legacy Activity table + const activityTypeMap: Record = { + KEY_BOUGHT: "buy", + KEY_SOLD: "sell", + KEY_BURNED: "burn", + KEY_TRANSFERRED_IN: "transfer_in", + KEY_TRANSFERRED_OUT: "transfer_out", + DIVIDEND_DISTRIBUTED: "dividend", + }; + const typeFilter = - type === 'buy' ? 'KEY_BOUGHT' : type === 'sell' ? 'KEY_SOLD' : undefined; + type === "buy" + ? "KEY_BOUGHT" + : type === "sell" + ? "KEY_SOLD" + : type === "burn" + ? "KEY_BURNED" + : type === "transfer_in" + ? "KEY_TRANSFERRED_IN" + : type === "transfer_out" + ? "KEY_TRANSFERRED_OUT" + : type === "dividend" + ? "DIVIDEND_DISTRIBUTED" + : undefined; - const where: any = { + const activityWhere: any = { actor: address, - type: typeFilter ? typeFilter : { in: ['KEY_BOUGHT', 'KEY_SOLD'] }, + type: typeFilter ? typeFilter : { in: ["KEY_BOUGHT", "KEY_SOLD"] }, }; - if (creator_id) { - where.creatorId = creator_id; + activityWhere.creatorId = creator_id; } - - // Date range filter: `from` and `to` are inclusive boundaries. if (from || to) { - where.createdAt = {}; - if (from) { - where.createdAt.gte = new Date(from); - } - if (to) { - where.createdAt.lte = new Date(to); - } + activityWhere.createdAt = {}; + if (from) activityWhere.createdAt.gte = new Date(from); + if (to) activityWhere.createdAt.lte = new Date(to); } let prismaCursor: { id: string } | undefined; @@ -59,97 +78,181 @@ export async function fetchWalletActivity( if (decoded && decoded.id) { prismaCursor = { id: decoded.id }; } + } catch (_e) {} + } + + // Query both sources safely (handling test mocks where only one table is mocked) + const [logRows, legacyRows, legacyCount] = await Promise.all([ + prisma.activityLog?.findMany + ? prisma.activityLog.findMany({ + where: logWhere, + orderBy: [{ timestamp: "desc" }, { id: "desc" }], + take: limit * 3, + }) + : Promise.resolve([]), + prisma.activity?.findMany + ? prisma.activity.findMany({ + where: activityWhere, + orderBy: [{ createdAt: "desc" }, { id: "desc" }], + skip: prismaCursor ? 1 : offset, + take: limit, + ...(prismaCursor ? { cursor: prismaCursor } : {}), + }) + : Promise.resolve([]), + prisma.activity?.count + ? prisma.activity.count({ where: activityWhere }).catch(() => 0) + : Promise.resolve(0), + ]); + + // Also query dividend claims for the address if dividend type matches + let dividendClaimRows: any[] = []; + if (!type || type === "dividend") { + try { + dividendClaimRows = await prisma.dividendClaim.findMany({ + where: { recipientAddress: address }, + include: { distribution: true }, + orderBy: [{ createdAt: "desc" }, { id: "desc" }], + take: limit * 3, + }); } catch (_e) { - // Ignore tampered cursor and fall back + // table might be empty } } - const [rows, total] = await Promise.all([ - prisma.activity.findMany({ - where, - orderBy: [{ createdAt: 'desc' }, { id: 'desc' }], - skip: prismaCursor ? 1 : offset, - take: limit, - ...(prismaCursor ? { cursor: prismaCursor } : {}), - }), - prisma.activity.count({ where }), - ]); + // Build unified list of items + const unifiedItems: WalletActivityItem[] = []; + const seenIds = new Set(); - if (rows.length === 0) { - return [[], total, null]; + // Add ActivityLog entries + for (const row of logRows) { + if (seenIds.has(row.id)) continue; + seenIds.add(row.id); + const kId = row.keyId || ""; + unifiedItems.push({ + id: row.id, + type: row.type as UnifiedActivityType, + keyId: kId, + creator_id: kId, + creatorName: row.creatorName || null, + creator_handle: row.creatorName || null, + amount: Number(row.amount ?? 0), + timestamp: row.timestamp, + txHash: row.txHash, + payload: row.payload, + } as any); } - // Resolve creator handles in a single batched query. - const creatorIds = [ + // Add legacy Activity entries + for (let i = 0; i < legacyRows.length; i++) { + const row = legacyRows[i]; + const mappedType = activityTypeMap[row.type]; + if (!mappedType) continue; + if (type && mappedType !== type) continue; + const rowId = row.id || `legacy-act-${i}-${row.createdAt ? new Date(row.createdAt).getTime() : Date.now()}`; + if (seenIds.has(rowId)) continue; + seenIds.add(rowId); + + const payload = (row.payload as Record) || {}; + const kId = row.creatorId || payload.keyId || ""; + unifiedItems.push({ + id: rowId, + type: mappedType, + keyId: kId, + creator_id: kId, + creatorName: null, + creator_handle: null, + amount: Number(payload.amount ?? 0), + timestamp: row.createdAt || new Date(), + txHash: payload.txHash || null, + price_at_trade: payload.price_at_trade, + fee_paid: payload.fee_paid, + ledger_sequence: payload.ledger_sequence ? Number(payload.ledger_sequence) : null, + }); + } + + // Add DividendClaim entries + for (const claim of dividendClaimRows) { + const id = `div_${claim.id}`; + if (seenIds.has(id)) continue; + seenIds.add(id); + + const kId = claim.distribution?.creatorId || ""; + unifiedItems.push({ + id, + type: "dividend", + keyId: kId, + creator_id: kId, + creatorName: null, + creator_handle: null, + amount: Number(claim.amountXlm ?? 0), + timestamp: claim.claimedAt || claim.createdAt, + txHash: claim.distribution?.txHash || null, + }); + } + + // Resolve creator names for items missing creatorName / creator_handle + const missingCreatorIds: string[] = [ ...new Set( - rows - .map((r: { creatorId: string | null }) => r.creatorId) - .filter(Boolean) + unifiedItems + .filter((item) => (!item.creatorName || !item.creator_handle) && Boolean(item.keyId)) + .map((item) => item.keyId as string) ), - ] as string[]; - const creatorProfiles = await prisma.creatorProfile.findMany({ - where: { id: { in: creatorIds } }, - select: { id: true, handle: true }, + ]; + + if (missingCreatorIds.length > 0) { + const creatorProfiles = await prisma.creatorProfile.findMany({ + where: { id: { in: missingCreatorIds } }, + select: { id: true, handle: true, displayName: true }, + }); + const nameMap = new Map(); + for (const cp of creatorProfiles) { + nameMap.set(cp.id, cp.displayName || cp.handle || cp.id); + } + for (const item of unifiedItems) { + if (item.keyId && nameMap.has(item.keyId)) { + const resolvedName = nameMap.get(item.keyId) || null; + item.creatorName = resolvedName; + item.creator_handle = resolvedName; + } + } + } + + // Sort unified items by timestamp descending + unifiedItems.sort((a, b) => { + const tA = new Date(a.timestamp).getTime(); + const tB = new Date(b.timestamp).getTime(); + if (tB !== tA) return tB - tA; + return b.id.localeCompare(a.id); }); - const handleMap = new Map( - creatorProfiles.map((c: { id: string; handle: string }) => [ - c.id, - c.handle, - ]) - ); - - const items: WalletActivityItem[] = rows.map( - (row: { - id: string; - type: string; - creatorId: string | null; - payload: unknown; - createdAt: Date; - }) => { - const payload = (row.payload ?? {}) as Record; - const type = row.type === 'KEY_BOUGHT' ? 'buy' : 'sell'; - - // A buy spends XLM (outgoing); a sell receives XLM (incoming). - let xlmDelta: string | null = null; - if (payload.price_at_trade != null) { - try { - xlmDelta = formatXlmDelta( - BigInt(payload.price_at_trade), - type === 'buy' ? 'out' : 'in' - ); - } catch (_e) { - xlmDelta = null; + + let total = legacyCount > 0 ? legacyCount : unifiedItems.length; + if (unifiedItems.length > total) total = unifiedItems.length; + + // Cursor-based pagination slice + let startIndex = 0; + if (cursor) { + try { + const decoded = decodeCursor(cursor); + if (decoded && decoded.id) { + const foundIdx = unifiedItems.findIndex((item) => item.id === decoded.id); + if (foundIdx !== -1) { + startIndex = foundIdx + 1; } } - - return { - id: row.id, - type, - creator_id: row.creatorId ?? '', - creator_handle: row.creatorId - ? (handleMap.get(row.creatorId) ?? null) - : null, - amount: payload.amount ?? null, - price_at_trade: payload.price_at_trade ?? null, - fee_paid: payload.fee_paid ?? null, - xlm_delta: xlmDelta, - ledger_sequence: - payload.ledger_sequence != null - ? Number(payload.ledger_sequence) - : null, - timestamp: row.createdAt, - }; + } catch (_e) { + // ignore invalid cursor } - ); - - const hasMore = prismaCursor - ? items.length === limit - : offset + limit < total; - let nextCursor: string | null = null; - if (hasMore && items.length > 0) { - const lastItem = items[items.length - 1]; - nextCursor = encodeCursor({ id: lastItem.id }); + } else if (offset) { + startIndex = offset; } - return [items, total, nextCursor]; + const pageItems = unifiedItems.slice(startIndex, startIndex + limit); + const lastItem = pageItems[pageItems.length - 1]; + const hasMore = startIndex + limit < unifiedItems.length || total > startIndex + limit; + const nextCursor = + hasMore && lastItem + ? encodeCursor({ id: lastItem.id }) + : null; + + return [pageItems, total, nextCursor]; } diff --git a/src/modules/wallets/wallet-activity.unified.integration.test.ts b/src/modules/wallets/wallet-activity.unified.integration.test.ts new file mode 100644 index 0000000..6c46c97 --- /dev/null +++ b/src/modules/wallets/wallet-activity.unified.integration.test.ts @@ -0,0 +1,196 @@ +import request from "supertest"; +import express from "express"; +import walletsRouter from "./wallets.routes"; +import * as walletActivityService from "./wallet-activity.service"; +import { signWalletAccessToken } from "../../utils/jwt.utils"; +import { errorHandler } from "../../middlewares/error.middleware"; + +const app = express(); +app.use(express.json()); +app.use("/wallets", walletsRouter); +app.use(errorHandler); + +const TEST_WALLET_1 = "GA2C5RFPE6GCKMY3US5PAB6UZLKIGAHWKXX2GIOVPWW27DD6W4KZYLMI"; +const TEST_WALLET_2 = "GBTESTWALLETADDRESSFORACCESSLAYERTESTINGSTELLARCONTRACT123"; + +describe("GET /wallets/:address/activity Unified Feed (#811)", () => { + let validToken: string; + + beforeAll(() => { + process.env.JWT_SECRET = "accesslayer_default_development_jwt_secret_key_32_bytes"; + validToken = signWalletAccessToken(TEST_WALLET_1); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it("returns 401 when Authorization header is missing", async () => { + const res = await request(app).get(`/wallets/${TEST_WALLET_1}/activity`); + expect(res.status).toBe(401); + }); + + it("returns 401 when JWT does not match the address param", async () => { + const res = await request(app) + .get(`/wallets/${TEST_WALLET_2}/activity`) + .set("Authorization", `Bearer ${validToken}`); + + expect(res.status).toBe(401); + }); + + it("returns 200 with empty array when wallet has no activity", async () => { + jest.spyOn(walletActivityService, "fetchWalletActivity").mockResolvedValue([ + [], + 0, + null, + ]); + + const res = await request(app) + .get(`/wallets/${TEST_WALLET_1}/activity`) + .set("Authorization", `Bearer ${validToken}`); + + expect(res.status).toBe(200); + expect(res.body.data.items).toEqual([]); + expect(res.body.data.meta.total).toBe(0); + }); + + it("returns all 6 event types correctly labelled and sorted by timestamp descending", async () => { + const mockEvents = [ + { + id: "act-1", + type: "dividend" as const, + keyId: "creator-alpha", + creatorName: "Alpha Creator", + amount: 50, + timestamp: new Date("2026-03-01T12:00:00Z"), + }, + { + id: "act-2", + type: "burn" as const, + keyId: "creator-alpha", + creatorName: "Alpha Creator", + amount: 2, + timestamp: new Date("2026-03-01T11:00:00Z"), + }, + { + id: "act-3", + type: "transfer_out" as const, + keyId: "creator-beta", + creatorName: "Beta Creator", + amount: 5, + timestamp: new Date("2026-03-01T10:00:00Z"), + }, + { + id: "act-4", + type: "transfer_in" as const, + keyId: "creator-beta", + creatorName: "Beta Creator", + amount: 10, + timestamp: new Date("2026-03-01T09:00:00Z"), + }, + { + id: "act-5", + type: "sell" as const, + keyId: "creator-gamma", + creatorName: "Gamma Creator", + amount: 3, + timestamp: new Date("2026-03-01T08:00:00Z"), + }, + { + id: "act-6", + type: "buy" as const, + keyId: "creator-gamma", + creatorName: "Gamma Creator", + amount: 8, + timestamp: new Date("2026-03-01T07:00:00Z"), + }, + ]; + + jest.spyOn(walletActivityService, "fetchWalletActivity").mockResolvedValue([ + mockEvents, + 6, + null, + ]); + + const res = await request(app) + .get(`/wallets/${TEST_WALLET_1}/activity`) + .set("Authorization", `Bearer ${validToken}`); + + expect(res.status).toBe(200); + const items = res.body.data.items; + expect(items).toHaveLength(6); + + const types = items.map((i: any) => i.type); + expect(types).toEqual([ + "dividend", + "burn", + "transfer_out", + "transfer_in", + "sell", + "buy", + ]); + + // Every item contains keyId, creatorName, amount, and timestamp + for (const item of items) { + expect(item).toHaveProperty("keyId"); + expect(item).toHaveProperty("creatorName"); + expect(item).toHaveProperty("amount"); + expect(item).toHaveProperty("timestamp"); + } + }); + + it("supports cursor pagination returning nextCursor", async () => { + const mockFirstPage = [ + { + id: "act-1", + type: "buy" as const, + keyId: "creator-1", + creatorName: "Creator 1", + amount: 1, + timestamp: new Date("2026-03-01T12:00:00Z"), + }, + ]; + + const cursor = "eyJpZCI6ImFjdC0xIn0="; + + jest.spyOn(walletActivityService, "fetchWalletActivity").mockImplementation( + async (_address, query) => { + if (query.cursor === cursor) { + return [ + [ + { + id: "act-2", + type: "sell" as const, + keyId: "creator-1", + creatorName: "Creator 1", + amount: 1, + timestamp: new Date("2026-03-01T11:00:00Z"), + }, + ], + 2, + null, + ]; + } + return [mockFirstPage, 2, cursor]; + } + ); + + // Fetch page 1 + const res1 = await request(app) + .get(`/wallets/${TEST_WALLET_1}/activity?limit=1`) + .set("Authorization", `Bearer ${validToken}`); + + expect(res1.status).toBe(200); + expect(res1.body.data.items[0].id).toBe("act-1"); + expect(res1.body.data.meta.nextCursor).toBe(cursor); + + // Fetch page 2 with cursor + const res2 = await request(app) + .get(`/wallets/${TEST_WALLET_1}/activity?limit=1&cursor=${cursor}`) + .set("Authorization", `Bearer ${validToken}`); + + expect(res2.status).toBe(200); + expect(res2.body.data.items[0].id).toBe("act-2"); + expect(res2.body.data.meta.nextCursor).toBeNull(); + }); +}); diff --git a/src/modules/wallets/wallets.routes.ts b/src/modules/wallets/wallets.routes.ts index 0495aae..2742213 100644 --- a/src/modules/wallets/wallets.routes.ts +++ b/src/modules/wallets/wallets.routes.ts @@ -1,20 +1,22 @@ -import { Router } from 'express'; -import { httpGetWalletActivity } from './wallet-activity.controllers'; -import { httpGetWalletHoldings } from './wallet-holdings.controllers'; -import { cacheControl } from '../../middlewares/cache-control.middleware'; -import { ACTIVITY_FEED_CACHE_PRESET } from '../../constants/activity-feed-cache.constants'; +import { Router } from "express"; +import { httpGetWalletActivity } from "./wallet-activity.controllers"; +import { httpGetWalletHoldings } from "./wallet-holdings.controllers"; +import { cacheControl } from "../../middlewares/cache-control.middleware"; +import { ACTIVITY_FEED_CACHE_PRESET } from "../../constants/activity-feed-cache.constants"; +import { requireWalletParamMatch } from "../../middlewares/jwt-auth.middleware"; const walletsRouter = Router(); /** * GET /api/v1/wallets/:address/activity * - * Returns the paginated trade history (buys and sells) for a given Stellar - * wallet address across all creators. Supports optional `type` (buy|sell) - * and `creator_id` filters. + * Returns the unified chronological on-chain activity feed for a wallet + * across buys, sells, transfers, burns, and dividends. + * Requires a valid JWT matching the address parameter. */ walletsRouter.get( - '/:address/activity', + "/:address/activity", + requireWalletParamMatch("address"), cacheControl(ACTIVITY_FEED_CACHE_PRESET), httpGetWalletActivity ); @@ -22,9 +24,8 @@ walletsRouter.get( /** * GET /api/v1/wallets/:address/holdings * - * Returns all creator key holdings for a given Stellar wallet address, - * including creator handle, key count, and latest known price. + * Returns all creator key holdings for a given Stellar wallet address. */ -walletsRouter.get('/:address/holdings', httpGetWalletHoldings); +walletsRouter.get("/:address/holdings", httpGetWalletHoldings); export default walletsRouter; diff --git a/src/modules/whitelist/whitelist.controllers.ts b/src/modules/whitelist/whitelist.controllers.ts index b4c978a..b00ab4a 100644 --- a/src/modules/whitelist/whitelist.controllers.ts +++ b/src/modules/whitelist/whitelist.controllers.ts @@ -4,7 +4,6 @@ import { sendValidationError, sendNotFound, } from '../../utils/api-response.utils'; -import { Response } from 'express'; import { GetWhitelistStatusQuery, GetWhitelistStatusQuerySchema, @@ -54,9 +53,7 @@ export const httpGetWhitelistStatus: AsyncController = async ( // Verify creator exists const exists = await creatorExists(creatorId); if (!exists) { - return sendNotFound(res, 'Creator not found', [ - { field: 'keyId', message: 'The specified key ID does not exist' }, - ]); + return sendNotFound(res, 'Creator'); } // Get whitelist status with caching diff --git a/src/utils/api-response.utils.ts b/src/utils/api-response.utils.ts index 329bde0..36bbc74 100644 --- a/src/utils/api-response.utils.ts +++ b/src/utils/api-response.utils.ts @@ -114,7 +114,7 @@ export function sendError( message: string, details?: Array<{ field?: string; message: string }> ): void { - res.setHeader('Content-Type', 'application/json'); + if (typeof res.setHeader === 'function') res.setHeader('Content-Type', 'application/json'); res.status(statusCode).json(buildErrorResponse(code, message, details)); } @@ -132,7 +132,7 @@ export function sendSuccess( data: serializeBigInt(data) as T, ...(message ? { message } : {}), }; - res.setHeader('Content-Type', 'application/json'); + if (typeof res.setHeader === 'function') res.setHeader('Content-Type', 'application/json'); res.status(statusCode).json(body); } @@ -152,7 +152,7 @@ export function sendPaginatedSuccess( meta, ...(message ? { message } : {}), }; - res.setHeader('Content-Type', 'application/json'); + if (typeof res.setHeader === 'function') res.setHeader('Content-Type', 'application/json'); res.status(statusCode).json(body); } diff --git a/src/utils/jwt.utils.ts b/src/utils/jwt.utils.ts index 3428212..d7a4c29 100644 --- a/src/utils/jwt.utils.ts +++ b/src/utils/jwt.utils.ts @@ -86,3 +86,22 @@ export function extractBearerToken(authHeader: unknown): string | undefined { if (!token || scheme?.toLowerCase() !== 'bearer') return undefined; return token.trim() || undefined; } + + + +export function decodeJwt(token: string): any { + return jwt.decode(token); +} + +export function signJwt( + payload: { sub?: string; wallet?: string } | string, + expiresInSeconds: number = envConfig.JWT_ACCESS_TOKEN_TTL_SECONDS +): string { + if (typeof payload === "string") { + return signWalletAccessToken(payload, undefined, expiresInSeconds); + } + const wallet = payload.wallet || payload.sub || ""; + return signWalletAccessToken(wallet, payload.sub, expiresInSeconds); +} + +export const JwtError = JwtVerifyError; diff --git a/src/utils/redis.utils.ts b/src/utils/redis.utils.ts index 084032d..644eac4 100644 --- a/src/utils/redis.utils.ts +++ b/src/utils/redis.utils.ts @@ -213,3 +213,6 @@ export async function disconnectRedis(): Promise { globalForRedis.__accesslayerRedis = undefined; } } + +export const getRedis = getRedisClient; +export const redis = getRedisClient; diff --git a/src/utils/soroban-rpc.utils.ts b/src/utils/soroban-rpc.utils.ts index ef8b491..9c24300 100644 --- a/src/utils/soroban-rpc.utils.ts +++ b/src/utils/soroban-rpc.utils.ts @@ -1,5 +1,5 @@ import { logger } from './logger.utils'; -import { envConfig } from '../config.schema'; +import { envConfig } from '../config'; /** * Soroban RPC client for querying contract state and ledger entries.