diff --git a/package-lock.json b/package-lock.json index 41dfd683..3ec5fbe4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4643,9 +4643,9 @@ "license": "MIT" }, "node_modules/@rollup/plugin-commonjs": { - "version": "29.0.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-29.0.2.tgz", - "integrity": "sha512-S/ggWH1LU7jTyi9DxZOKyxpVd4hF/OZ0JrEbeLjXk/DFXwRny0tjD2c992zOUYQobLrVkRVMDdmHP16HKP7GRg==", + "version": "29.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-29.0.3.tgz", + "integrity": "sha512-ZaOxZceP7SOUW7Lqw5IRVweSQYWaeIPnXIGLiB690EBA3FGJTO40EEr2L5yZplJWsgTCogILRSpcAe7+U0Otdg==", "dev": true, "license": "MIT", "dependencies": { @@ -4813,9 +4813,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", - "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", "cpu": [ "arm" ], @@ -4827,9 +4827,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", - "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", "cpu": [ "arm64" ], @@ -4841,9 +4841,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", - "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", "cpu": [ "arm64" ], @@ -4855,9 +4855,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", - "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", "cpu": [ "x64" ], @@ -4869,9 +4869,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", - "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", "cpu": [ "arm64" ], @@ -4883,9 +4883,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", - "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", "cpu": [ "x64" ], @@ -4897,13 +4897,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", - "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4911,13 +4914,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", - "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4925,13 +4931,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", - "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4939,13 +4948,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", - "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4953,13 +4965,16 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", - "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", "cpu": [ "loong64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4967,13 +4982,16 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", - "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", "cpu": [ "loong64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4981,13 +4999,16 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", - "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4995,13 +5016,16 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", - "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -5009,13 +5033,16 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", - "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -5023,13 +5050,16 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", - "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -5037,13 +5067,16 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", - "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -5051,13 +5084,16 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", - "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -5065,13 +5101,16 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", - "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -5079,9 +5118,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", - "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", "cpu": [ "x64" ], @@ -5093,9 +5132,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", - "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", "cpu": [ "arm64" ], @@ -5107,9 +5146,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", - "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", "cpu": [ "arm64" ], @@ -5121,9 +5160,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", - "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", "cpu": [ "ia32" ], @@ -5135,9 +5174,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", - "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", "cpu": [ "x64" ], @@ -5149,9 +5188,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", - "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", "cpu": [ "x64" ], @@ -6173,9 +6212,9 @@ } }, "node_modules/@sveltejs/acorn-typescript": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.8.tgz", - "integrity": "sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.10.tgz", + "integrity": "sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA==", "dev": true, "license": "MIT", "peerDependencies": { @@ -6288,9 +6327,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, @@ -6520,20 +6559,6 @@ "@types/node": "*" } }, - "node_modules/@typescript-eslint/types": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.1.tgz", - "integrity": "sha512-S29BOBPJSFUiblEl6RzPPjJt6w25A6XsBqRVDt53tA/tlL8q7ceQNZHTjPeONt/3S7KRI4quk+yP9jK2WjBiPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@whatwg-node/disposablestack": { "version": "0.0.5", "dev": true, @@ -7190,20 +7215,20 @@ } }, "node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", - "content-type": "^1.0.5", + "content-type": "^2.0.0", "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" }, "engines": { "node": ">=18" @@ -7213,6 +7238,19 @@ "url": "https://opencollective.com/express" } }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/bootstrap": { "version": "4.6.2", "dev": true, @@ -9233,14 +9271,21 @@ } }, "node_modules/esrap": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.4.tgz", - "integrity": "sha512-suICpxAmZ9A8bzJjEl/+rLJiDKC0X4gYWUxT6URAWBLvlXmtbZd5ySMu/N2ZGEtMCAmflUDPSehrP9BQcsGcSg==", + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.12.tgz", + "integrity": "sha512-On0QbLyaiAkVC4eXtgnXK9Kh2opit+3rcUSOc45DqJ2s/X2eXAHsGOKRSJ6IDagQEW5vPyivANfXUiqgXC67Rw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15", + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "peerDependencies": { "@typescript-eslint/types": "^8.2.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/types": { + "optional": true + } } }, "node_modules/esrecurse": { @@ -12772,9 +12817,9 @@ } }, "node_modules/mocha": { - "version": "11.7.5", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", - "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "version": "11.7.6", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.6.tgz", + "integrity": "sha512-nS9xOGbw2I3cjCpxwZAEJ9xK9lmJ08vEkQvLtz4du9ZrF9UrjRpeJGiIgl2Z+Qs++pmB4ecDe48Fwsh+j+j7xA==", "dev": true, "license": "MIT", "dependencies": { @@ -12972,9 +13017,9 @@ "license": "MIT" }, "node_modules/nock": { - "version": "14.0.13", - "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.13.tgz", - "integrity": "sha512-SCPsQmGVNY8h1rfS3aU0MzOGYY+wKIFukHEsoSIwPRCYocZkya7MFIlWIEYPWQZj+Gaksg6EyUaY255ZDqpQuA==", + "version": "14.0.15", + "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.15.tgz", + "integrity": "sha512-S0a47C9pLvcYx/Ugf0H30BVBEcUgMMBDk9VJIDlJ8XGrfH2QDUD4Tgdp45qDIiHttokBG+IbsOtsvIjGR/j3bg==", "dev": true, "license": "MIT", "dependencies": { @@ -13474,9 +13519,9 @@ } }, "node_modules/npm-run-all2": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-9.0.1.tgz", - "integrity": "sha512-ZtK8WXZBUA9x0XD6nxYdFLe86FxpkCTq2LiQxzX0LeXQY/vyAigQZXjjj/xfTwgV4Yqe/vYNIq2W09lrHKTcuQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-9.0.2.tgz", + "integrity": "sha512-+dd4SO2jAlLE06OzmJKzIe6QvvjXezcbmobnh8usR0a8BzQCABTdqTXqVPji0ICOhSQpIIrkGd7IzNl5iDaRSA==", "dev": true, "license": "MIT", "dependencies": { @@ -13484,9 +13529,9 @@ "cross-spawn": "^7.0.6", "memorystream": "^0.3.1", "picomatch": "^4.0.2", - "pidtree": "^0.6.0", + "pidtree": "^1.0.0", "read-package-json-fast": "^6.0.0", - "shell-quote": "^1.7.3", + "shell-quote": "^1.8.4", "which": "^7.0.0" }, "bin": { @@ -14471,14 +14516,16 @@ } }, "node_modules/pidtree": { - "version": "0.6.0", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-1.0.0.tgz", + "integrity": "sha512-avfAvjB9Dd0wdj3rjJX//yS+G79OO0KrS5pJHFJENjYGX6N4SMgEDBBI/yFy0lloOYSaC6XQxzpOAMPfSYFV/Q==", "dev": true, "license": "MIT", "bin": { "pidtree": "bin/pidtree.js" }, "engines": { - "node": ">=0.10" + "node": ">=18" } }, "node_modules/pify": { @@ -15910,13 +15957,13 @@ } }, "node_modules/rollup": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", - "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@types/estree": "1.0.9" }, "bin": { "rollup": "dist/bin/rollup" @@ -15926,31 +15973,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.2", - "@rollup/rollup-android-arm64": "4.60.2", - "@rollup/rollup-darwin-arm64": "4.60.2", - "@rollup/rollup-darwin-x64": "4.60.2", - "@rollup/rollup-freebsd-arm64": "4.60.2", - "@rollup/rollup-freebsd-x64": "4.60.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", - "@rollup/rollup-linux-arm-musleabihf": "4.60.2", - "@rollup/rollup-linux-arm64-gnu": "4.60.2", - "@rollup/rollup-linux-arm64-musl": "4.60.2", - "@rollup/rollup-linux-loong64-gnu": "4.60.2", - "@rollup/rollup-linux-loong64-musl": "4.60.2", - "@rollup/rollup-linux-ppc64-gnu": "4.60.2", - "@rollup/rollup-linux-ppc64-musl": "4.60.2", - "@rollup/rollup-linux-riscv64-gnu": "4.60.2", - "@rollup/rollup-linux-riscv64-musl": "4.60.2", - "@rollup/rollup-linux-s390x-gnu": "4.60.2", - "@rollup/rollup-linux-x64-gnu": "4.60.2", - "@rollup/rollup-linux-x64-musl": "4.60.2", - "@rollup/rollup-openbsd-x64": "4.60.2", - "@rollup/rollup-openharmony-arm64": "4.60.2", - "@rollup/rollup-win32-arm64-msvc": "4.60.2", - "@rollup/rollup-win32-ia32-msvc": "4.60.2", - "@rollup/rollup-win32-x64-gnu": "4.60.2", - "@rollup/rollup-win32-x64-msvc": "4.60.2", + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", "fsevents": "~2.3.2" } }, @@ -16985,15 +17032,15 @@ } }, "node_modules/svelte": { - "version": "5.55.7", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.7.tgz", - "integrity": "sha512-ymI5ykLPwIHW839E053FQbI1G+jnRFJEw3Kv5Y4njixVWywQBx+NUFpkkKyk5LIb36Fg9DVXSYpqiGekLD0hyw==", + "version": "5.56.4", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.56.4.tgz", + "integrity": "sha512-/d0QHehmRuJW8gVz395MTkPcPozxzdjBMBE8oEYGz8O3b9KTMzzQ9ZHJQLuFKOHOPQbU6kx/X4iid/EBBzH7iw==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", - "@sveltejs/acorn-typescript": "^1.0.5", + "@sveltejs/acorn-typescript": "^1.0.10", "@types/estree": "^1.0.5", "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", @@ -17002,7 +17049,7 @@ "clsx": "^2.1.1", "devalue": "^5.8.1", "esm-env": "^1.2.1", - "esrap": "^2.2.4", + "esrap": "^2.2.12", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", @@ -17056,7 +17103,9 @@ } }, "node_modules/svelte-preprocess": { - "version": "6.0.3", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-6.0.5.tgz", + "integrity": "sha512-sgwew5yV/2eMeQobIWgAxCNarKwiTUDIc3siAUbq3sp0G6ONtzk0W+wJihMdqjbYb3iGU3ubpGv0usnnuXT3qg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -17074,7 +17123,7 @@ "stylus": ">=0.55", "sugarss": "^2.0.0 || ^3.0.0 || ^4.0.0", "svelte": "^4.0.0 || ^5.0.0-next.100 || ^5.0.0", - "typescript": "^5.0.0" + "typescript": "^5.0.0 || ^6.0.0" }, "peerDependenciesMeta": { "@babel/core": { @@ -17442,17 +17491,34 @@ } }, "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", "license": "MIT", "dependencies": { - "content-type": "^1.0.5", + "content-type": "^2.0.0", "media-typer": "^1.1.0", "mime-types": "^3.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/type-is/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/type-is/node_modules/mime-db": { @@ -18191,7 +18257,7 @@ "dependencies": { "@aws-sdk/client-s3": "^3.1037.0", "async-didi": "^1.0.0", - "body-parser": "^2.2.2", + "body-parser": "^2.3.0", "compression": "^1.8.1", "express-session": "^1.19.0", "fake-tag": "^5.0.0", @@ -18214,10 +18280,10 @@ "@types/sinon": "^21.0.1", "chai": "^6.2.2", "graphql": "^17.0.0", - "mocha": "^11.7.5", - "nock": "^14.0.13", + "mocha": "^11.7.6", + "nock": "^14.0.15", "nodemon": "^3.1.14", - "npm-run-all2": "^9.0.0", + "npm-run-all2": "^9.0.2", "sinon": "^22.0.0", "sinon-chai": "^4.0.0", "typescript": "^5.9.3" @@ -18241,24 +18307,24 @@ "version": "0.75.0", "devDependencies": { "@bpmn-io/draggle": "^4.1.2", - "@rollup/plugin-commonjs": "^29.0.2", + "@rollup/plugin-commonjs": "^29.0.3", "@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-terser": "^1.0.0", "@rollup/plugin-url": "^8.0.2", "bootstrap": "^4.6.1", "eslint-plugin-svelte": "^3.17.1", "min-dash": "^5.0.0", - "npm-run-all2": "^9.0.0", + "npm-run-all2": "^9.0.2", "octicons": "^8.5.0", "postcss": "^8.5.12", - "rollup": "^4.60.2", + "rollup": "^4.62.2", "rollup-plugin-copy": "^3.5.0", "rollup-plugin-css-only": "^4.5.5", "rollup-plugin-string": "^3.0.0", "rollup-plugin-svelte": "^7.2.3", "sass": "^1.77.4", - "svelte": "^5.55.7", - "svelte-preprocess": "^6.0.3" + "svelte": "^5.56.4", + "svelte-preprocess": "^6.0.5" }, "engines": { "node": ">= 20" diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 154329bf..ca607e09 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -6,6 +6,16 @@ All notable changes to [wuffle](https://github.com/nikku/wuffle) are documented _**Note:** Yet to be released changes appear here._ +## 0.76.0 + +* `FEAT`: support GitHub sub-issues ([#313](https://github.com/nikku/wuffle/pull/313)) +* `FEAT`: validate GitHub application on startup ([#313](https://github.com/nikku/wuffle/pull/313)) +* `DEPS`: update to `body-parser@2.3.0` + +### Breaking Changes + +* Application requires `sub_issues` events for full synchronization to work + ## 0.75.0 * `FEAT`: synchronize standard fields for comment authors diff --git a/packages/app/app.yml b/packages/app/app.yml index 4a5b5109..4bd59d11 100644 --- a/packages/app/app.yml +++ b/packages/app/app.yml @@ -46,6 +46,7 @@ default_events: # - team # - team_add # - watch +- sub_issues # The set of permissions needed by the GitHub App. The format of the object uses # the permission name for the key (for example, issues) and the access type for diff --git a/packages/app/lib/apps/events-sync/EventsSync.js b/packages/app/lib/apps/events-sync/EventsSync.js index 44bcd8d6..aa24a368 100644 --- a/packages/app/lib/apps/events-sync/EventsSync.js +++ b/packages/app/lib/apps/events-sync/EventsSync.js @@ -227,12 +227,29 @@ export default function EventsSync(webhookEvents, store, logger) { }); - // issues /////////////////////////////// + // sub-issues ///////////////////// - // https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#issues - // issue transfer is mapped to the following GitHub events + // https://docs.github.com/en/webhooks/webhook-events-and-payloads#sub_issues + // + // update sub-issues on change - updating parent <> child relationship + webhookEvents.on( + /** @type {any} */ ([ 'sub_issues.sub_issue_added', 'sub_issues.sub_issue_removed' ]), + async ({ payload }) => { + + const { + sub_issue, + repository + } = /** @type {any} */ (payload); + + return store.updateIssue(filterIssue(sub_issue, repository)); + } + ); + + + // https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#issues // + // issue transfer is mapped to the following GitHub events: // -> issues.opened (new issue is being opened by GitHub) // -> issues.transferred (old issue was deleted by GitHub) // diff --git a/packages/app/lib/apps/github-app/GithubApp.js b/packages/app/lib/apps/github-app/GithubApp.js index 9ee08f53..970b25ea 100644 --- a/packages/app/lib/apps/github-app/GithubApp.js +++ b/packages/app/lib/apps/github-app/GithubApp.js @@ -19,11 +19,13 @@ const RequiredEvents = [ 'issues', 'issue_comment', 'label', + 'member', 'milestone', 'pull_request', 'pull_request_review', 'repository', - 'status' + 'status', + 'sub_issues' ]; /** @@ -41,8 +43,9 @@ const RequiredEvents = [ * @param {import('../../types.js').ProbotApp} app * @param {import('../../types.js').Logger} logger * @param {import('../../types.js').Injector} injector + * @param {import('../../events.js').default} events */ -export default function GithubApp(config, app, logger, injector) { +export default function GithubApp(config, app, logger, injector, events) { const log = logger.child({ name: 'wuffle:github-app' @@ -266,6 +269,31 @@ export default function GithubApp(config, app, logger, injector) { log.debug('validated installations'); } + async function validateApp() { + const octokit = await getAppScopedClient(); + const { data: app } = await octokit.rest.apps.getAuthenticated(); + + // app may not be configured yet + if (!app) { + return; + } + + const missingEvents = RequiredEvents.filter( + event => !app.events.includes(event) + ); + + if (missingEvents.length) { + log.error({ + missingEvents, + events: app.events + }, 'app is missing required event subscriptions; update app settings on GitHub'); + } + } + + events.once('wuffle.start', async function() { + await validateApp().catch(err => log.warn({ err }, 'failed to validate app configuration')); + }); + /** * Fetch active installations. * diff --git a/packages/app/lib/filters.js b/packages/app/lib/filters.js index 41b29ad9..9494df37 100644 --- a/packages/app/lib/filters.js +++ b/packages/app/lib/filters.js @@ -214,7 +214,8 @@ export function filterIssue(githubIssue, githubRepository) { milestone, pull_request, html_url, - author_association + author_association, + parent_issue_url } = githubIssue; // stable ID that is independent from GitHubs internal issue/pr distinction @@ -245,7 +246,8 @@ export function filterIssue(githubIssue, githubRepository) { repository: filterRepository(githubRepository), pull_request: !!pull_request, html_url, - author_association + author_association, + parent_issue_url: parent_issue_url || null }; } \ No newline at end of file diff --git a/packages/app/lib/util/links.js b/packages/app/lib/util/links.js index 0de9be3a..f643c6e9 100644 --- a/packages/app/lib/util/links.js +++ b/packages/app/lib/util/links.js @@ -145,6 +145,22 @@ export function findLinks(issue, types) { links.push(link); } + // add CHILD_OF link from parent_issue_url (GitHub sub-issues) + const { parent_issue_url } = issue; + + if (parent_issue_url) { + const parentMatch = parent_issue_url.match(/\/repos\/([^/]+)\/([^/]+)\/issues\/(\d+)/); + + if (parentMatch) { + links.push({ + type: CHILD_OF, + owner: parentMatch[1], + repo: parentMatch[2], + number: parseInt(parentMatch[3], 10) + }); + } + } + if (typeof types !== 'undefined') { return filterLinks(links, types); } diff --git a/packages/app/package.json b/packages/app/package.json index 69674be1..53af4d03 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -44,7 +44,7 @@ "dependencies": { "@aws-sdk/client-s3": "^3.1037.0", "async-didi": "^1.0.0", - "body-parser": "^2.2.2", + "body-parser": "^2.3.0", "compression": "^1.8.1", "express-session": "^1.19.0", "fake-tag": "^5.0.0", @@ -64,10 +64,10 @@ "@types/sinon": "^21.0.1", "chai": "^6.2.2", "graphql": "^17.0.0", - "mocha": "^11.7.5", - "nock": "^14.0.13", + "mocha": "^11.7.6", + "nock": "^14.0.15", "nodemon": "^3.1.14", - "npm-run-all2": "^9.0.0", + "npm-run-all2": "^9.0.2", "sinon": "^22.0.0", "sinon-chai": "^4.0.0", "typescript": "^5.9.3" diff --git a/packages/app/test/apps/events-sync/EventsSync.test.js b/packages/app/test/apps/events-sync/EventsSync.test.js index 741b41f5..7c9ca67d 100644 --- a/packages/app/test/apps/events-sync/EventsSync.test.js +++ b/packages/app/test/apps/events-sync/EventsSync.test.js @@ -924,6 +924,48 @@ describe('apps/events-sync', function() { }); }); + + it('sub_issues.sub_issue_added', async function() { + + // when + await webhookEvents.emit( + event('16-sub_issues.sub_issue_added') + ); + + // then + expectIssue(store, { + key: 'nikku/testtest#131', + number: 131, + title: 'Sub issue', + repository: { + name: 'testtest' + }, + pull_request: false, + state: 'open', + parent_issue_url: 'https://api.github.com/repos/nikku/testtest/issues/130' + }); + }); + + + it('sub_issues.sub_issue_removed', async function() { + + // given + await webhookEvents.emit( + event('16-sub_issues.sub_issue_added') + ); + + // when + await webhookEvents.emit( + event('17-sub_issues.sub_issue_removed') + ); + + // then + expectIssue(store, { + key: 'nikku/testtest#131', + parent_issue_url: null + }); + }); + }); }); diff --git a/packages/app/test/apps/events-sync/fixtures/16-sub_issues.sub_issue_added.json b/packages/app/test/apps/events-sync/fixtures/16-sub_issues.sub_issue_added.json new file mode 100644 index 00000000..4ccc8034 --- /dev/null +++ b/packages/app/test/apps/events-sync/fixtures/16-sub_issues.sub_issue_added.json @@ -0,0 +1,80 @@ +{ + "name": "sub_issues", + "payload": { + "action": "sub_issue_added", + "parent_issue_id": 4411391091, + "parent_issue": { + "url": "https://api.github.com/repos/nikku/testtest/issues/130", + "id": 4411391091, + "number": 130, + "title": "New issue", + "state": "open" + }, + "parent_issue_repo": { + "id": 150751504, + "name": "testtest", + "owner": { + "login": "nikku" + } + }, + "sub_issue_id": 4411391092, + "sub_issue": { + "url": "https://api.github.com/repos/nikku/testtest/issues/131", + "repository_url": "https://api.github.com/repos/nikku/testtest", + "html_url": "https://github.com/nikku/testtest/issues/131", + "id": 4411391092, + "node_id": "I_kwDOCPxJEM8AAAABBvB8dA", + "number": 131, + "title": "Sub issue", + "user": { + "login": "nikku", + "id": 58601, + "node_id": "MDQ6VXNlcjU4NjAx", + "avatar_url": "https://avatars.githubusercontent.com/u/58601?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nikku", + "html_url": "https://github.com/nikku", + "type": "User", + "site_admin": false + }, + "labels": [], + "state": "open", + "locked": false, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2026-05-09T06:00:00Z", + "updated_at": "2026-05-09T06:00:00Z", + "closed_at": null, + "assignee": null, + "author_association": "OWNER", + "active_lock_reason": null, + "body": null, + "state_reason": null, + "parent_issue_url": "https://api.github.com/repos/nikku/testtest/issues/130" + }, + "repository": { + "id": 150751504, + "node_id": "MDEwOlJlcG9zaXRvcnkxNTA3NTE1MDQ=", + "name": "testtest", + "full_name": "nikku/testtest", + "private": false, + "owner": { + "login": "nikku", + "id": 58601, + "node_id": "MDQ6VXNlcjU4NjAx", + "avatar_url": "https://avatars.githubusercontent.com/u/58601?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nikku", + "html_url": "https://github.com/nikku", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/nikku/testtest" + }, + "installation": { + "id": 48472471, + "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNDg0NzI0NzE=" + } + } +} diff --git a/packages/app/test/apps/events-sync/fixtures/17-sub_issues.sub_issue_removed.json b/packages/app/test/apps/events-sync/fixtures/17-sub_issues.sub_issue_removed.json new file mode 100644 index 00000000..046b7bf0 --- /dev/null +++ b/packages/app/test/apps/events-sync/fixtures/17-sub_issues.sub_issue_removed.json @@ -0,0 +1,80 @@ +{ + "name": "sub_issues", + "payload": { + "action": "sub_issue_removed", + "parent_issue_id": 4411391091, + "parent_issue": { + "url": "https://api.github.com/repos/nikku/testtest/issues/130", + "id": 4411391091, + "number": 130, + "title": "New issue", + "state": "open" + }, + "parent_issue_repo": { + "id": 150751504, + "name": "testtest", + "owner": { + "login": "nikku" + } + }, + "sub_issue_id": 4411391092, + "sub_issue": { + "url": "https://api.github.com/repos/nikku/testtest/issues/131", + "repository_url": "https://api.github.com/repos/nikku/testtest", + "html_url": "https://github.com/nikku/testtest/issues/131", + "id": 4411391092, + "node_id": "I_kwDOCPxJEM8AAAABBvB8dA", + "number": 131, + "title": "Sub issue", + "user": { + "login": "nikku", + "id": 58601, + "node_id": "MDQ6VXNlcjU4NjAx", + "avatar_url": "https://avatars.githubusercontent.com/u/58601?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nikku", + "html_url": "https://github.com/nikku", + "type": "User", + "site_admin": false + }, + "labels": [], + "state": "open", + "locked": false, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2026-05-09T06:00:00Z", + "updated_at": "2026-05-09T06:00:01Z", + "closed_at": null, + "assignee": null, + "author_association": "OWNER", + "active_lock_reason": null, + "body": null, + "state_reason": null, + "parent_issue_url": null + }, + "repository": { + "id": 150751504, + "node_id": "MDEwOlJlcG9zaXRvcnkxNTA3NTE1MDQ=", + "name": "testtest", + "full_name": "nikku/testtest", + "private": false, + "owner": { + "login": "nikku", + "id": 58601, + "node_id": "MDQ6VXNlcjU4NjAx", + "avatar_url": "https://avatars.githubusercontent.com/u/58601?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nikku", + "html_url": "https://github.com/nikku", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/nikku/testtest" + }, + "installation": { + "id": 48472471, + "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNDg0NzI0NzE=" + } + } +} diff --git a/packages/app/test/apps/github-app/GithubApp.test.js b/packages/app/test/apps/github-app/GithubApp.test.js new file mode 100644 index 00000000..cdafe5d8 --- /dev/null +++ b/packages/app/test/apps/github-app/GithubApp.test.js @@ -0,0 +1,164 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; + +import AsyncEvents from 'wuffle/lib/events.js'; +import GithubApp from 'wuffle/lib/apps/github-app/GithubApp.js'; + + +const AllRequiredEvents = [ + 'check_run', + 'create', + 'issues', + 'issue_comment', + 'label', + 'member', + 'milestone', + 'pull_request', + 'pull_request_review', + 'repository', + 'status', + 'sub_issues' +]; + + +describe('apps/github-app', function() { + + let warnSpy, errorSpy, events; + + function createGithubApp(options = {}) { + const { + appEvents = AllRequiredEvents, + installations = [] + } = options; + + const logger = { + child() { return this; }, + warn: warnSpy, + error: errorSpy, + debug() {}, + info() {} + }; + + const mockOctokit = { + rest: { + apps: { + getAuthenticated() { + return Promise.resolve({ data: { events: appEvents } }); + }, + listInstallations: {} + } + }, + paginate() { + return Promise.resolve(installations); + } + }; + + const mockApp = { + auth() { + return Promise.resolve(mockOctokit); + } + }; + + const mockInjector = { + get() { + return Promise.resolve({ on() {} }); + } + }; + + return new GithubApp({}, /** @type {any} */ (mockApp), /** @type {any} */ (logger), /** @type {any} */ (mockInjector), events); + } + + function createInstallation(overrides = {}) { + return { + id: 1, + account: { login: 'test-org' }, + permissions: { + checks: 'read', + contents: 'read', + issues: 'write', + metadata: 'read', + pull_requests: 'write', + statuses: 'read' + }, + events: AllRequiredEvents, + ...overrides + }; + } + + beforeEach(function() { + warnSpy = sinon.spy(); + errorSpy = sinon.spy(); + events = new AsyncEvents(); + }); + + + describe('validateApp', function() { + + it('should log error if app is missing required event subscriptions', async function() { + + // given + createGithubApp({ appEvents: [ 'issues', 'pull_request' ] }); + + // when + await events.emit('wuffle.start'); + + // then + expect(errorSpy).to.have.been.calledWithMatch( + sinon.match.has('missingEvents'), + 'app is missing required event subscriptions; update app settings on GitHub' + ); + }); + + + it('should not log error if app has all required event subscriptions', async function() { + + // given + createGithubApp({ appEvents: AllRequiredEvents }); + + // when + await events.emit('wuffle.start'); + + // then + expect(errorSpy).not.to.have.been.called; + }); + + }); + + + describe('validateInstallation', function() { + + it('should warn if installation is missing required event subscriptions', async function() { + + // given + const githubApp = createGithubApp({ + installations: [ createInstallation({ events: [ 'issues', 'pull_request' ] }) ] + }); + + // when + await githubApp.getInstallations(); + + // then + expect(warnSpy).to.have.been.calledWithMatch( + sinon.match.has('missingEvents'), + 'missing required event subscriptions' + ); + }); + + + it('should not warn if installation has all required event subscriptions', async function() { + + // given + const githubApp = createGithubApp({ + installations: [ createInstallation({ events: AllRequiredEvents }) ] + }); + + // when + await githubApp.getInstallations(); + + // then + expect(warnSpy).not.to.have.been.called; + }); + + }); + +}); diff --git a/packages/app/test/fixtures/filters/filtered/issue-with-milestone.json b/packages/app/test/fixtures/filters/filtered/issue-with-milestone.json index c6c727e4..60be45c2 100644 --- a/packages/app/test/fixtures/filters/filtered/issue-with-milestone.json +++ b/packages/app/test/fixtures/filters/filtered/issue-with-milestone.json @@ -53,5 +53,6 @@ }, "pull_request": true, "html_url": "https://github.com/nikku/testtest/pull/75", - "author_association": "OWNER" + "author_association": "OWNER", + "parent_issue_url": null } \ No newline at end of file diff --git a/packages/app/test/store.test.js b/packages/app/test/store.test.js index 02dc8554..76ecac2c 100644 --- a/packages/app/test/store.test.js +++ b/packages/app/test/store.test.js @@ -482,40 +482,106 @@ describe('store', function() { }; - it('should establish', async function() { + describe('should establish', function() { - // given - const store = createStore(); + it('basic', async function() { - const issue_1 = await store.updateIssue(createIssue({ - repository - })); + // given + const store = createStore(); - const issue_2 = await store.updateIssue(createIssue({ - repository: otherRepository - })); + const issue_1 = await store.updateIssue(createIssue({ + repository + })); - // when - const issue = await store.updateIssue(createIssue({ - title: `Closes #${issue_1.number}`, - repository, - body: ` - Depends on ${issue_2.repository.owner.login}/${issue_2.repository.name}#${issue_2.number} - ` - })); + const issue_2 = await store.updateIssue(createIssue({ + repository: otherRepository + })); + + // when + const issue = await store.updateIssue(createIssue({ + title: `Closes #${issue_1.number}`, + repository, + body: ` + Depends on ${issue_2.repository.owner.login}/${issue_2.repository.name}#${issue_2.number} + ` + })); + + // then + const updates = store.updates.getSince(); + + expect(updates).to.have.length(3); + + const issue_links = store.getIssueLinks(issue); + + expect(issue_links).to.have.length(2); + + const issue_1_links = store.getIssueLinks(issue_1); + + expect(issue_1_links).to.have.length(1); + }); - // then - const updates = store.updates.getSince(); - expect(updates).to.have.length(3); + it('CHILD_OF from parent_issue_url', async function() { - const issue_links = store.getIssueLinks(issue); + // given + const store = createStore(); + + const parentIssue = await store.updateIssue(createIssue({ repository })); + + // when + const childIssue = await store.updateIssue(createIssue({ + repository, + parent_issue_url: `https://api.github.com/repos/${repository.owner.login}/${repository.name}/issues/${parentIssue.number}` + })); + + // then + const parentLinks = store.getIssueLinks(parentIssue); + + expect(parentLinks).to.have.length(1); + expect(parentLinks[0].type).to.eql('PARENT_OF'); + expect(parentLinks[0].target.id).to.eql(childIssue.id); - expect(issue_links).to.have.length(2); + const childLinks = store.getIssueLinks(childIssue); + + expect(childLinks).to.have.length(1); + expect(childLinks[0].type).to.eql('CHILD_OF'); + expect(childLinks[0].target.id).to.eql(parentIssue.id); + }); - const issue_1_links = store.getIssueLinks(issue_1); - expect(issue_1_links).to.have.length(1); + it('deduplicating PARENT_OF / CHILD_OF', async function() { + + // given + const store = createStore(); + + const childIssue = await store.updateIssue(createIssue({ repository })); + + // parent references child both via task list body AND GitHub sub-issue + const parentIssue = await store.updateIssue(createIssue({ + repository, + body: `* [ ] #${childIssue.number}` + })); + + // when + await store.updateIssue({ + ...childIssue, + parent_issue_url: `https://api.github.com/repos/${repository.owner.login}/${repository.name}/issues/${parentIssue.number}` + }); + + // then + // only one PARENT_OF link, not two + const parentLinks = store.getIssueLinks(parentIssue); + + expect(parentLinks).to.have.length(1); + expect(parentLinks[0].type).to.eql('PARENT_OF'); + + // only one CHILD_OF link, not two + const childLinks = store.getIssueLinks(childIssue); + + expect(childLinks).to.have.length(1); + expect(childLinks[0].type).to.eql('CHILD_OF'); + }); + }); diff --git a/packages/app/test/util.test.js b/packages/app/test/util.test.js index 169268cb..3e9f3d99 100644 --- a/packages/app/test/util.test.js +++ b/packages/app/test/util.test.js @@ -619,6 +619,32 @@ describe('util', function() { }); + it('should recognize sub-issues via parent_issue_url', function() { + + // given + const issue = createIssue( + 'FOO', + null, + { + parent_issue_url: 'https://api.github.com/repos/foo/bar/issues/42' + } + ); + + // when + const links = findLinks(issue); + + // then + expect(links).to.eql([ + { + type: CHILD_OF, + owner: 'foo', + repo: 'bar', + number: 42 + } + ]); + }); + + it('should recognize task lists', function() { // given @@ -1284,11 +1310,12 @@ describe('util', function() { // helpers ///////////////////////// -function createIssue(title, body) { +function createIssue(title, body, extraFields = {}) { return { title, - body + body, + ...extraFields }; } diff --git a/packages/board/package.json b/packages/board/package.json index 9ed75879..acafd0bf 100644 --- a/packages/board/package.json +++ b/packages/board/package.json @@ -4,24 +4,24 @@ "private": true, "devDependencies": { "@bpmn-io/draggle": "^4.1.2", - "@rollup/plugin-commonjs": "^29.0.2", + "@rollup/plugin-commonjs": "^29.0.3", "@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-terser": "^1.0.0", "@rollup/plugin-url": "^8.0.2", "bootstrap": "^4.6.1", "eslint-plugin-svelte": "^3.17.1", "min-dash": "^5.0.0", - "npm-run-all2": "^9.0.0", + "npm-run-all2": "^9.0.2", "octicons": "^8.5.0", "postcss": "^8.5.12", - "rollup": "^4.60.2", + "rollup": "^4.62.2", "rollup-plugin-copy": "^3.5.0", "rollup-plugin-css-only": "^4.5.5", "rollup-plugin-string": "^3.0.0", "rollup-plugin-svelte": "^7.2.3", "sass": "^1.77.4", - "svelte": "^5.55.7", - "svelte-preprocess": "^6.0.3" + "svelte": "^5.56.4", + "svelte-preprocess": "^6.0.5" }, "engines": { "node": ">= 20"