From a530a4828fba3daa52a5989426bffde9d5aae7af Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Thu, 2 Nov 2023 13:11:38 +0100 Subject: [PATCH 01/16] feat: implement downloader --- package.json | 4 + pnpm-lock.yaml | 447 +++++++++++++++++++++++++++++++++++++++++++++- src/downloader.ts | 127 +++++++++++++ src/main.ts | 39 ++-- 4 files changed, 594 insertions(+), 23 deletions(-) create mode 100644 src/downloader.ts diff --git a/package.json b/package.json index 28be4137..e42d7c74 100644 --- a/package.json +++ b/package.json @@ -149,13 +149,17 @@ "@biomejs/biome": "^1.2.2", "@types/node": "^18.17.5", "@types/resolve": "^1.20.2", + "@types/semver": "^7.5.4", "@types/vscode": "^1.80.0", "@vscode/vsce": "^2.20.1", "esbuild": "^0.19.2", "typescript": "^5.1.6" }, "dependencies": { + "octokit": "^3.1.1", + "ofetch": "^1.3.3", "resolve": "^1.22.4", + "semver": "^7.5.4", "vscode-languageclient": "^8.1.0" }, "vsce": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 251a8e16..790414f8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,9 +5,18 @@ settings: excludeLinksFromLockfile: false dependencies: + octokit: + specifier: ^3.1.1 + version: 3.1.1 + ofetch: + specifier: ^1.3.3 + version: 1.3.3 resolve: specifier: ^1.22.4 version: 1.22.4 + semver: + specifier: ^7.5.4 + version: 7.5.4 vscode-languageclient: specifier: ^8.1.0 version: 8.1.0 @@ -22,6 +31,9 @@ devDependencies: '@types/resolve': specifier: ^1.20.2 version: 1.20.2 + '@types/semver': + specifier: ^7.5.4 + version: 7.5.4 '@types/vscode': specifier: ^1.80.0 version: 1.80.0 @@ -303,14 +315,279 @@ packages: dev: true optional: true + /@octokit/app@14.0.1: + resolution: {integrity: sha512-4opdXcWBVhzd6FOxlaxDKXXqi9Vz2hsDSWQGNo49HbYFAX11UqMpksMjEdfvHy0x19Pse8Nvn+R6inNb/V398w==} + engines: {node: '>= 18'} + dependencies: + '@octokit/auth-app': 6.0.1 + '@octokit/auth-unauthenticated': 5.0.1 + '@octokit/core': 5.0.1 + '@octokit/oauth-app': 6.0.0 + '@octokit/plugin-paginate-rest': 9.1.2(@octokit/core@5.0.1) + '@octokit/types': 12.1.1 + '@octokit/webhooks': 12.0.3 + dev: false + + /@octokit/auth-app@6.0.1: + resolution: {integrity: sha512-tjCD4nzQNZgmLH62+PSnTF6eGerisFgV4v6euhqJik6yWV96e1ZiiGj+NXIqbgnpjLmtnBqVUrNyGKu3DoGEGA==} + engines: {node: '>= 18'} + dependencies: + '@octokit/auth-oauth-app': 7.0.1 + '@octokit/auth-oauth-user': 4.0.1 + '@octokit/request': 8.1.4 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.1.1 + deprecation: 2.3.1 + lru-cache: 10.0.1 + universal-github-app-jwt: 1.1.1 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/auth-oauth-app@7.0.1: + resolution: {integrity: sha512-RE0KK0DCjCHXHlQBoubwlLijXEKfhMhKm9gO56xYvFmP1QTMb+vvwRPmQLLx0V+5AvV9N9I3lr1WyTzwL3rMDg==} + engines: {node: '>= 18'} + dependencies: + '@octokit/auth-oauth-device': 6.0.1 + '@octokit/auth-oauth-user': 4.0.1 + '@octokit/request': 8.1.4 + '@octokit/types': 12.1.1 + '@types/btoa-lite': 1.0.1 + btoa-lite: 1.0.0 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/auth-oauth-device@6.0.1: + resolution: {integrity: sha512-yxU0rkL65QkjbqQedgVx3gmW7YM5fF+r5uaSj9tM/cQGVqloXcqP2xK90eTyYvl29arFVCW8Vz4H/t47mL0ELw==} + engines: {node: '>= 18'} + dependencies: + '@octokit/oauth-methods': 4.0.0 + '@octokit/request': 8.1.4 + '@octokit/types': 12.1.1 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/auth-oauth-user@4.0.1: + resolution: {integrity: sha512-N94wWW09d0hleCnrO5wt5MxekatqEJ4zf+1vSe8MKMrhZ7gAXKFOKrDEZW2INltvBWJCyDUELgGRv8gfErH1Iw==} + engines: {node: '>= 18'} + dependencies: + '@octokit/auth-oauth-device': 6.0.1 + '@octokit/oauth-methods': 4.0.0 + '@octokit/request': 8.1.4 + '@octokit/types': 12.1.1 + btoa-lite: 1.0.0 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/auth-token@4.0.0: + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} + dev: false + + /@octokit/auth-unauthenticated@5.0.1: + resolution: {integrity: sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==} + engines: {node: '>= 18'} + dependencies: + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.1.1 + dev: false + + /@octokit/core@5.0.1: + resolution: {integrity: sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==} + engines: {node: '>= 18'} + dependencies: + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.0.2 + '@octokit/request': 8.1.4 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.1.1 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/endpoint@9.0.2: + resolution: {integrity: sha512-qhKW8YLIi+Kmc92FQUFGr++DYtkx/1fBv+Thua6baqnjnOsgBYJDCvWZR1YcINuHGOEQt416WOfE+A/oG60NBQ==} + engines: {node: '>= 18'} + dependencies: + '@octokit/types': 12.1.1 + is-plain-object: 5.0.0 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/graphql@7.0.2: + resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==} + engines: {node: '>= 18'} + dependencies: + '@octokit/request': 8.1.4 + '@octokit/types': 12.1.1 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/oauth-app@6.0.0: + resolution: {integrity: sha512-bNMkS+vJ6oz2hCyraT9ZfTpAQ8dZNqJJQVNaKjPLx4ue5RZiFdU1YWXguOPR8AaSHS+lKe+lR3abn2siGd+zow==} + engines: {node: '>= 18'} + dependencies: + '@octokit/auth-oauth-app': 7.0.1 + '@octokit/auth-oauth-user': 4.0.1 + '@octokit/auth-unauthenticated': 5.0.1 + '@octokit/core': 5.0.1 + '@octokit/oauth-authorization-url': 6.0.2 + '@octokit/oauth-methods': 4.0.0 + '@types/aws-lambda': 8.10.125 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/oauth-authorization-url@6.0.2: + resolution: {integrity: sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA==} + engines: {node: '>= 18'} + dev: false + + /@octokit/oauth-methods@4.0.0: + resolution: {integrity: sha512-dqy7BZLfLbi3/8X8xPKUKZclMEK9vN3fK5WF3ortRvtplQTszFvdAGbTo71gGLO+4ZxspNiLjnqdd64Chklf7w==} + engines: {node: '>= 18'} + dependencies: + '@octokit/oauth-authorization-url': 6.0.2 + '@octokit/request': 8.1.4 + '@octokit/request-error': 5.0.1 + '@octokit/types': 11.1.0 + btoa-lite: 1.0.0 + dev: false + + /@octokit/openapi-types@18.1.1: + resolution: {integrity: sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==} + dev: false + + /@octokit/openapi-types@19.0.2: + resolution: {integrity: sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ==} + dev: false + + /@octokit/plugin-paginate-graphql@4.0.0(@octokit/core@5.0.1): + resolution: {integrity: sha512-7HcYW5tP7/Z6AETAPU14gp5H5KmCPT3hmJrS/5tO7HIgbwenYmgw4OY9Ma54FDySuxMwD+wsJlxtuGWwuZuItA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=5' + dependencies: + '@octokit/core': 5.0.1 + dev: false + + /@octokit/plugin-paginate-rest@9.1.2(@octokit/core@5.0.1): + resolution: {integrity: sha512-euDbNV6fxX6btsCDnZoZM4vw3zO1nj1Z7TskHAulO6mZ9lHoFTpwll6farf+wh31mlBabgU81bBYdflp0GLVAQ==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=5' + dependencies: + '@octokit/core': 5.0.1 + '@octokit/types': 12.1.1 + dev: false + + /@octokit/plugin-rest-endpoint-methods@10.1.2(@octokit/core@5.0.1): + resolution: {integrity: sha512-JztgZ82CY4JNlPTuF0jh4iWuuGpEi5czFCoXyAbMg4F2XyFBbG5DWAKfa3odRvdZww6Df1tQgBKnqpd9X0WF9g==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=5' + dependencies: + '@octokit/core': 5.0.1 + '@octokit/types': 12.1.1 + dev: false + + /@octokit/plugin-retry@6.0.1(@octokit/core@5.0.1): + resolution: {integrity: sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=5' + dependencies: + '@octokit/core': 5.0.1 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.1.1 + bottleneck: 2.19.5 + dev: false + + /@octokit/plugin-throttling@8.1.2(@octokit/core@5.0.1): + resolution: {integrity: sha512-oFba+ioR6HGb0fgqxMta7Kpk/MdffUTuUxNY856l1nXPvh7Qggp8w4AksRx1SDA8SGd+4cbrpkY4k1J/Xz8nZQ==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': ^5.0.0 + dependencies: + '@octokit/core': 5.0.1 + '@octokit/types': 12.1.1 + bottleneck: 2.19.5 + dev: false + + /@octokit/request-error@5.0.1: + resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==} + engines: {node: '>= 18'} + dependencies: + '@octokit/types': 12.1.1 + deprecation: 2.3.1 + once: 1.4.0 + dev: false + + /@octokit/request@8.1.4: + resolution: {integrity: sha512-M0aaFfpGPEKrg7XoA/gwgRvc9MSXHRO2Ioki1qrPDbl1e9YhjIwVoHE7HIKmv/m3idzldj//xBujcFNqGX6ENA==} + engines: {node: '>= 18'} + dependencies: + '@octokit/endpoint': 9.0.2 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.1.1 + is-plain-object: 5.0.0 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/types@11.1.0: + resolution: {integrity: sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==} + dependencies: + '@octokit/openapi-types': 18.1.1 + dev: false + + /@octokit/types@12.1.1: + resolution: {integrity: sha512-qnJTldJ1NyGT5MTsCg/Zi+y2IFHZ1Jo5+njNCjJ9FcainV7LjuHgmB697kA0g4MjZeDAJsM3B45iqCVsCLVFZg==} + dependencies: + '@octokit/openapi-types': 19.0.2 + dev: false + + /@octokit/webhooks-methods@4.0.0: + resolution: {integrity: sha512-M8mwmTXp+VeolOS/kfRvsDdW+IO0qJ8kYodM/sAysk093q6ApgmBXwK1ZlUvAwXVrp/YVHp6aArj4auAxUAOFw==} + engines: {node: '>= 18'} + dev: false + + /@octokit/webhooks-types@7.1.0: + resolution: {integrity: sha512-y92CpG4kFFtBBjni8LHoV12IegJ+KFxLgKRengrVjKmGE5XMeCuGvlfRe75lTRrgXaG6XIWJlFpIDTlkoJsU8w==} + dev: false + + /@octokit/webhooks@12.0.3: + resolution: {integrity: sha512-8iG+/yza7hwz1RrQ7i7uGpK2/tuItZxZq1aTmeg2TNp2xTUB8F8lZF/FcZvyyAxT8tpDMF74TjFGCDACkf1kAQ==} + engines: {node: '>= 18'} + dependencies: + '@octokit/request-error': 5.0.1 + '@octokit/webhooks-methods': 4.0.0 + '@octokit/webhooks-types': 7.1.0 + aggregate-error: 3.1.0 + dev: false + + /@types/aws-lambda@8.10.125: + resolution: {integrity: sha512-Vqw/WMlV4O1fJT6capim01v7VLDZkcX1n6Yhb52E7IfnMqYbNfwHfyDV8rRN42NLBtdDvfaqcCqs2K0fr5ljZw==} + dev: false + + /@types/btoa-lite@1.0.1: + resolution: {integrity: sha512-YwCjy5v1THSaj5KrBz0SKwKYtjwT0YpOm8VB4TR6DzyvTa503T+rE0Ku6Q3DUKtm1rzNrEXyqdYHpcLiYN6oXg==} + dev: false + + /@types/jsonwebtoken@9.0.4: + resolution: {integrity: sha512-8UYapdmR0QlxgvJmyE8lP7guxD0UGVMfknsdtCFZh4ovShdBl3iOI4zdvqBHrB/IS+xUj3PSx73Qkey1fhWz+g==} + dependencies: + '@types/node': 18.17.5 + dev: false + /@types/node@18.17.5: resolution: {integrity: sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==} - dev: true /@types/resolve@1.20.2: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} dev: true + /@types/semver@7.5.4: + resolution: {integrity: sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==} + dev: true + /@types/vscode@1.80.0: resolution: {integrity: sha512-qK/CmOdS2o7ry3k6YqU4zD3R2AYlJfbwBoSbKpBoP+GpXNE+0NEgJOli4n0bm0diK5kfBnchgCEj4igQz/44Hg==} dev: true @@ -344,6 +621,14 @@ packages: keytar: 7.9.0 dev: true + /aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: false + /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -371,6 +656,10 @@ packages: dev: true optional: true + /before-after-hook@2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + dev: false + /bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} requiresBuild: true @@ -385,6 +674,10 @@ packages: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true + /bottleneck@2.19.5: + resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} + dev: false + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -398,10 +691,18 @@ packages: balanced-match: 1.0.2 dev: false + /btoa-lite@1.0.0: + resolution: {integrity: sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==} + dev: false + /buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} dev: true + /buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + dev: false + /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} requiresBuild: true @@ -457,6 +758,11 @@ packages: dev: true optional: true + /clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: false + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -507,6 +813,14 @@ packages: dev: true optional: true + /deprecation@2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + dev: false + + /destr@2.0.2: + resolution: {integrity: sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==} + dev: false + /detect-libc@2.0.2: resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} engines: {node: '>=8'} @@ -541,6 +855,12 @@ packages: domhandler: 5.0.3 dev: true + /ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} requiresBuild: true @@ -688,6 +1008,11 @@ packages: dev: true optional: true + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: false + /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: @@ -711,10 +1036,46 @@ packages: has: 1.0.3 dev: false + /is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + dev: false + /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} dev: true + /jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + dependencies: + jws: 3.2.2 + 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.5.4 + dev: false + + /jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + dev: false + + /jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + dev: false + /keytar@7.9.0: resolution: {integrity: sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==} requiresBuild: true @@ -735,6 +1096,39 @@ packages: uc.micro: 1.0.6 dev: true + /lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + dev: false + + /lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + dev: false + + /lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + dev: false + + /lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + dev: false + + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: false + + /lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + dev: false + + /lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + dev: false + + /lru-cache@10.0.1: + resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==} + engines: {node: 14 || >=16.14} + dev: false + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -794,6 +1188,10 @@ packages: dev: true optional: true + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + /mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} dev: true @@ -819,6 +1217,10 @@ packages: dev: true optional: true + /node-fetch-native@1.4.1: + resolution: {integrity: sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w==} + dev: false + /nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} dependencies: @@ -829,11 +1231,34 @@ packages: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} dev: true + /octokit@3.1.1: + resolution: {integrity: sha512-AKJs5XYs7iAh7bskkYpxhUIpsYZdLqjnlnqrN5s9FFZuJ/a6ATUHivGpUKDpGB/xa+LGDtG9Lu8bOCfPM84vHQ==} + engines: {node: '>= 18'} + dependencies: + '@octokit/app': 14.0.1 + '@octokit/core': 5.0.1 + '@octokit/oauth-app': 6.0.0 + '@octokit/plugin-paginate-graphql': 4.0.0(@octokit/core@5.0.1) + '@octokit/plugin-paginate-rest': 9.1.2(@octokit/core@5.0.1) + '@octokit/plugin-rest-endpoint-methods': 10.1.2(@octokit/core@5.0.1) + '@octokit/plugin-retry': 6.0.1(@octokit/core@5.0.1) + '@octokit/plugin-throttling': 8.1.2(@octokit/core@5.0.1) + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.1.1 + dev: false + + /ofetch@1.3.3: + resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==} + dependencies: + destr: 2.0.2 + node-fetch-native: 1.4.1 + ufo: 1.3.1 + dev: false + /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 - dev: true /parse-semver@1.1.1: resolution: {integrity: sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==} @@ -953,8 +1378,6 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} requiresBuild: true - dev: true - optional: true /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -1085,10 +1508,25 @@ packages: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} dev: true + /ufo@1.3.1: + resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==} + dev: false + /underscore@1.13.6: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} dev: true + /universal-github-app-jwt@1.1.1: + resolution: {integrity: sha512-G33RTLrIBMFmlDV4u4CBF7dh71eWwykck4XgaxaIVeZKOYZRAAxvcGMRFTUclVY6xoUPQvO4Ne5wKGxYm/Yy9w==} + dependencies: + '@types/jsonwebtoken': 9.0.4 + jsonwebtoken: 9.0.2 + dev: false + + /universal-user-agent@6.0.0: + resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} + dev: false + /url-join@4.0.1: resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} dev: true @@ -1126,7 +1564,6 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true /xml2js@0.5.0: resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} diff --git a/src/downloader.ts b/src/downloader.ts new file mode 100644 index 00000000..654c9613 --- /dev/null +++ b/src/downloader.ts @@ -0,0 +1,127 @@ +import { Octokit } from "octokit"; +import { ExtensionContext, Uri, window, workspace } from "vscode"; +import { coerce, rcompare } from "semver"; +import { ofetch } from "ofetch"; +import { chmodSync } from "node:fs"; + +export const selectAndDownload = async (context: ExtensionContext) => { + const versions = await getVersions(context); + const version = await askVersion(versions); + await download(version, context); +}; + +/** + * Download the Biome CLI from GitHub + * + * @param version The version to download + */ +const download = async (version: string, context: ExtensionContext) => { + // Find the correct asset to download + const octokit = new Octokit(); + + const release = await octokit.request( + "GET /repos/{owner}/{repo}/releases/tags/{tag}", + { + owner: "biomejs", + repo: "biome", + tag: `cli/v${version}`, + }, + ); + + const platformArch = `${process.platform}-${process.arch}`; + + // Find the asset for the current platform + const asset = release.data.assets.find( + (asset) => + asset.name === + `biome-${platformArch}${process.platform === "win32" ? ".exe" : ""}`, + ); + + if (!asset) { + window.showErrorMessage( + `The specified version is not available for your platform/architecture (${platformArch}).`, + ); + } + + const bin = await ofetch(asset.browser_download_url, { + responseType: "arrayBuffer", + }); + + // Write binary file to disk + await workspace.fs.writeFile( + Uri.joinPath( + context.globalStorageUri, + "server", + `biome${process.platform === "win32" ? ".exe" : ""}`, + ), + new Uint8Array(bin), + ); + + // Make biome executable + chmodSync( + Uri.joinPath( + context.globalStorageUri, + "server", + `biome${process.platform === "win32" ? ".exe" : ""}`, + ).fsPath, + 0o755, + ); +}; + +/** + * Display the VS Code prompt for selection the version + */ +const askVersion = async (versions: string[]): Promise => { + const options = versions.map((version, index) => ({ + label: version, + description: index === 0 ? "(latest)" : "", + })); + + const result = await window.showQuickPick(options, { + placeHolder: "Select the version of the biome CLI to install", + }); + + return result?.label; +}; + +/** + * Retrieves the list of versions of the CLI. + * + * The calls to the API are cached for 1 hour to prevent hitting the rate limit. + */ +const getVersions = async (context: ExtensionContext): Promise => { + const cachedVersions = context.globalState.get<{ + expires_at: Date; + versions: string[]; + }>("biome_versions_cache"); + + // If the cache exists and is still valid, return it + if (cachedVersions && new Date(cachedVersions.expires_at) > new Date()) { + return cachedVersions.versions; + } + + const octokit = new Octokit(); + + // Retrieve all tags on the biome repository + const tags = await octokit.request("GET /repos/{owner}/{repo}/tags", { + owner: "biomejs", + repo: "biome", + per_page: 50, + }); + + const versions = tags.data + .filter((tag) => tag.name.startsWith("cli/")) + .map((tag) => tag.name.replace("cli/", "")) + .map((tag) => coerce(tag)) + .sort((a, b) => rcompare(a, b)) + .filter((tag) => tag?.version !== null) + .map((tag) => tag?.version); + + // Cache the result for 1 hour + await context.globalState.update("biome_versions_cache", { + expires_at: new Date(Date.now() + 60 * 60 * 1000), + versions, + }); + + return versions; +}; diff --git a/src/main.ts b/src/main.ts index 6c2489d3..14413af2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -27,6 +27,7 @@ import { setContextValue } from "./utils"; import resolveImpl = require("resolve/async"); import { createRequire } from "module"; import type * as resolve from "resolve"; +import { selectAndDownload } from "./downloader"; const resolveAsync = promisify( resolveImpl, @@ -61,15 +62,24 @@ export async function activate(context: ExtensionContext) { ); } - const command = await getServerPath(context, outputChannel); + let command = await getServerPath(context, outputChannel); if (!command) { - await window.showErrorMessage( - "The Biome extensions doesn't ship with prebuilt binaries for your platform yet. " + - "You can still use it by cloning the biomejs/biome repo from GitHub to build the LSP " + - "yourself and use it with this extension with the biome.lspBin setting", + const action = await window.showWarningMessage( + "Could not find Biome in your dependencies. Either add the @biomejs/biome package to your dependencies, or download the Biome CLI.", + "Ok", + "Download Biome", ); - return; + + if (action === "Download Biome") { + await selectAndDownload(context); + } + + command = await getServerPath(context, outputChannel); + + if (!command) { + return; + } } outputChannel.appendLine(`Using Biome from ${command}`); @@ -286,18 +296,11 @@ async function getBundledBinary( context: ExtensionContext, outputChannel: OutputChannel, ) { - const triplet = PLATFORMS[process.platform]?.[process.arch]?.triplet; - if (!triplet) { - outputChannel.appendLine( - `Unsupported platform ${process.platform} ${process.arch}`, - ); - return undefined; - } - - const binaryExt = triplet.includes("windows") ? ".exe" : ""; - const binaryName = `biome${binaryExt}`; - - const bundlePath = Uri.joinPath(context.extensionUri, "server", binaryName); + const bundlePath = Uri.joinPath( + context.globalStorageUri, + "server", + `biome${process.platform === "win32" ? ".exe" : ""}`, + ); const bundleExists = await fileExists(bundlePath); if (!bundleExists) { outputChannel.appendLine( From 929984571b36eb0870f689e9f77a9b019fe339b8 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Thu, 2 Nov 2023 13:15:58 +0100 Subject: [PATCH 02/16] reorganize imports --- src/downloader.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/downloader.ts b/src/downloader.ts index 654c9613..104f26ed 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -1,8 +1,8 @@ +import { chmodSync } from "node:fs"; import { Octokit } from "octokit"; -import { ExtensionContext, Uri, window, workspace } from "vscode"; -import { coerce, rcompare } from "semver"; import { ofetch } from "ofetch"; -import { chmodSync } from "node:fs"; +import { coerce, rcompare } from "semver"; +import { ExtensionContext, Uri, window, workspace } from "vscode"; export const selectAndDownload = async (context: ExtensionContext) => { const versions = await getVersions(context); From dcd5da7bcda4e2ebfc536b4ab930146ae4a5a601 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Thu, 2 Nov 2023 16:13:39 +0100 Subject: [PATCH 03/16] add updater --- src/commands/index.ts | 1 + src/downloader.ts | 13 ++++++++- src/main.ts | 62 ++++++++++++++++++++++++++++++++----------- src/statusBar.ts | 60 ++++++++++++++++++++++++++++++++++++++--- 4 files changed, 115 insertions(+), 21 deletions(-) diff --git a/src/commands/index.ts b/src/commands/index.ts index 72515dae..e649dec0 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -3,4 +3,5 @@ export enum Commands { RestartLspServer = "biome.restartLspServer", SyntaxTree = "biome.syntaxTree", ServerStatus = "biome.serverStatus", + UpdateBiome = "biome.updateBiome", } diff --git a/src/downloader.ts b/src/downloader.ts index 104f26ed..20dea8c6 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -10,6 +10,12 @@ export const selectAndDownload = async (context: ExtensionContext) => { await download(version, context); }; +export const updateToLatest = async (context: ExtensionContext) => { + const versions = await getVersions(context); + const version = versions[0]; + await download(version, context); +}; + /** * Download the Biome CLI from GitHub * @@ -66,6 +72,9 @@ const download = async (version: string, context: ExtensionContext) => { ).fsPath, 0o755, ); + + // Record latest version + await context.globalState.update("bundled_biome_version", version); }; /** @@ -89,7 +98,9 @@ const askVersion = async (versions: string[]): Promise => { * * The calls to the API are cached for 1 hour to prevent hitting the rate limit. */ -const getVersions = async (context: ExtensionContext): Promise => { +export const getVersions = async ( + context: ExtensionContext, +): Promise => { const cachedVersions = context.globalState.get<{ expires_at: Date; versions: string[]; diff --git a/src/main.ts b/src/main.ts index 14413af2..185cf557 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,6 +7,7 @@ import { OutputChannel, TextEditor, Uri, + commands, languages, window, workspace, @@ -27,7 +28,7 @@ import { setContextValue } from "./utils"; import resolveImpl = require("resolve/async"); import { createRequire } from "module"; import type * as resolve from "resolve"; -import { selectAndDownload } from "./downloader"; +import { selectAndDownload, updateToLatest } from "./downloader"; const resolveAsync = promisify( resolveImpl, @@ -62,9 +63,9 @@ export async function activate(context: ExtensionContext) { ); } - let command = await getServerPath(context, outputChannel); + let server = await getServerPath(context, outputChannel); - if (!command) { + if (!server.command) { const action = await window.showWarningMessage( "Could not find Biome in your dependencies. Either add the @biomejs/biome package to your dependencies, or download the Biome CLI.", "Ok", @@ -75,21 +76,22 @@ export async function activate(context: ExtensionContext) { await selectAndDownload(context); } - command = await getServerPath(context, outputChannel); + server = await getServerPath(context, outputChannel); - if (!command) { + if (!server.command) { return; } } - outputChannel.appendLine(`Using Biome from ${command}`); + outputChannel.appendLine(`Using Biome from ${server.command}`); - const statusBar = new StatusBar(); + const statusBar = new StatusBar(context); + await statusBar.setUsingBundledBiome(server.bundled); const serverOptions: ServerOptions = createMessageTransports.bind( undefined, outputChannel, - command, + server.command, ); const documentSelector: DocumentFilter[] = [ @@ -122,6 +124,23 @@ export async function activate(context: ExtensionContext) { // we are now in a biome project setContextValue(IN_BIOME_PROJECT, true); + commands.registerCommand(Commands.UpdateBiome, async (version: string) => { + console.log(version); + const result = await window.showInformationMessage( + `Are you sure you want to update Biome (bundled) to ${version} ?`, + { + modal: true, + }, + "Update", + "Cancel", + ); + + if (result === "Update") { + await updateToLatest(context); + statusBar.checkForUpdates(); + } + }); + session.registerCommand(Commands.SyntaxTree, syntaxTree(session)); session.registerCommand(Commands.ServerStatus, () => { traceOutputChannel.show(); @@ -209,29 +228,40 @@ const PLATFORMS: PlatformTriplets = { async function getServerPath( context: ExtensionContext, outputChannel: OutputChannel, -): Promise { +): Promise<{ bundled: boolean; command: string } | undefined> { // Only allow the bundled Biome binary in untrusted workspaces if (!workspace.isTrusted) { - return getBundledBinary(context, outputChannel); + return { + bundled: true, + command: await getBundledBinary(context, outputChannel), + }; } if (process.env.DEBUG_SERVER_PATH) { outputChannel.appendLine( `Biome DEBUG_SERVER_PATH detected: ${process.env.DEBUG_SERVER_PATH}`, ); - return process.env.DEBUG_SERVER_PATH; + return { + bundled: false, + command: process.env.DEBUG_SERVER_PATH, + }; } const config = workspace.getConfiguration(); const explicitPath = config.get("biome.lspBin"); if (typeof explicitPath === "string" && explicitPath !== "") { - return getWorkspaceRelativePath(explicitPath); + return { + bundled: false, + command: await getWorkspaceRelativePath(explicitPath), + }; } - return ( - (await getWorkspaceDependency(outputChannel)) ?? - (await getBundledBinary(context, outputChannel)) - ); + const workspaceDependency = await getWorkspaceDependency(outputChannel); + return { + bundled: workspaceDependency === undefined, + command: + workspaceDependency ?? (await getBundledBinary(context, outputChannel)), + }; } // Resolve `path` as relative to the workspace root diff --git a/src/statusBar.ts b/src/statusBar.ts index ce0c560e..486bc598 100644 --- a/src/statusBar.ts +++ b/src/statusBar.ts @@ -1,7 +1,15 @@ -import { StatusBarAlignment, StatusBarItem, ThemeColor, window } from "vscode"; +import { gt } from "semver"; +import { + ExtensionContext, + StatusBarAlignment, + StatusBarItem, + ThemeColor, + window, +} from "vscode"; import { State } from "vscode-languageclient"; import { LanguageClient } from "vscode-languageclient/node"; import { Commands } from "./commands"; +import { getVersions } from "./downloader"; /** * Enumeration of all the status the extension can display @@ -21,13 +29,15 @@ enum Status { } export class StatusBar { + private usingBundledBiome = false; private statusBarItem: StatusBarItem; + private statusBarUpdateItem: StatusBarItem; private serverState: State = State.Starting; private isActive = false; private serverVersion = ""; - constructor() { + constructor(private readonly context: ExtensionContext) { this.statusBarItem = window.createStatusBarItem( "biome.status", StatusBarAlignment.Right, @@ -36,7 +46,15 @@ export class StatusBar { this.statusBarItem.name = "Biome"; this.statusBarItem.command = Commands.ServerStatus; + + this.statusBarUpdateItem = window.createStatusBarItem( + "biome.update", + StatusBarAlignment.Right, + -2, + ); + this.update(); + this.checkForUpdates(); } public setServerState(client: LanguageClient, state: State) { @@ -70,8 +88,9 @@ export class StatusBar { status = Status.Error; } - this.statusBarItem.text = - `$(${status}) Biome ${this.serverVersion}`.trimEnd(); + this.statusBarItem.text = `$(${status}) Biome ${this.serverVersion} ${ + this.usingBundledBiome ? "(bundled)" : "" + }`.trimEnd(); switch (status) { case Status.Pending: { @@ -131,4 +150,37 @@ export class StatusBar { public hide() { this.statusBarItem.hide(); } + + public async setUsingBundledBiome(usingBundledBiome: boolean) { + this.usingBundledBiome = usingBundledBiome; + await this.checkForUpdates(); + } + + public async checkForUpdates() { + const latestVersion = (await getVersions(this.context))[0]; + const hasUpdates = gt( + latestVersion, + this.context.globalState.get("bundled_biome_version") ?? "0.0.0", + ); + + if (this.usingBundledBiome && hasUpdates) { + this.statusBarUpdateItem.name = "Biome update"; + this.statusBarUpdateItem.text = + "Biome update available $(cloud-download)"; + + this.statusBarUpdateItem.tooltip = "Click to update Biome"; + this.statusBarUpdateItem.backgroundColor = new ThemeColor( + "statusBarItem.warningBackground", + ); + this.statusBarUpdateItem.show(); + + this.statusBarUpdateItem.command = { + title: "Update Biome", + command: Commands.UpdateBiome, + arguments: [latestVersion], + }; + } else { + this.statusBarUpdateItem.hide(); + } + } } From 889aa26ffe46f2cce8a69d77026cf3ad1950fbd8 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Fri, 3 Nov 2023 16:04:34 +0100 Subject: [PATCH 04/16] add version switcher and progress bars --- src/commands/index.ts | 1 + src/downloader.ts | 53 +++++++++++++++++++++++++++++++++++++------ src/main.ts | 7 +++++- src/statusBar.ts | 11 +++++++++ 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/commands/index.ts b/src/commands/index.ts index e649dec0..2c242c52 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -4,4 +4,5 @@ export enum Commands { SyntaxTree = "biome.syntaxTree", ServerStatus = "biome.serverStatus", UpdateBiome = "biome.updateBiome", + ChangeVersion = "biome.changeVersion", } diff --git a/src/downloader.ts b/src/downloader.ts index 20dea8c6..a53d710d 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -1,19 +1,58 @@ import { chmodSync } from "node:fs"; import { Octokit } from "octokit"; import { ofetch } from "ofetch"; -import { coerce, rcompare } from "semver"; -import { ExtensionContext, Uri, window, workspace } from "vscode"; +import { coerce, gt, gte, rcompare } from "semver"; +import { + ExtensionContext, + ProgressLocation, + Uri, + commands, + window, + workspace, +} from "vscode"; +import { Commands } from "./commands"; export const selectAndDownload = async (context: ExtensionContext) => { - const versions = await getVersions(context); + const versions = await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Fetching Biome versions", + cancellable: false, + }, + async () => { + return await getVersions(context); + }, + ); + const version = await askVersion(versions); - await download(version, context); + + await window.withProgress( + { + location: ProgressLocation.Notification, + title: `Updating Biome to ${version}`, + cancellable: false, + }, + async () => { + await download(version, context); + await commands.executeCommand(Commands.RestartLspServer); + }, + ); }; export const updateToLatest = async (context: ExtensionContext) => { - const versions = await getVersions(context); - const version = versions[0]; - await download(version, context); + await window.withProgress( + { + location: ProgressLocation.Notification, + title: "Updating Biome version", + cancellable: false, + }, + async () => { + const versions = await getVersions(context); + const version = versions[0]; + await download(version, context); + await commands.executeCommand(Commands.RestartLspServer); + }, + ); }; /** diff --git a/src/main.ts b/src/main.ts index 185cf557..198db789 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,6 +5,7 @@ import { TextDecoder, promisify } from "util"; import { ExtensionContext, OutputChannel, + ProgressLocation, TextEditor, Uri, commands, @@ -125,7 +126,6 @@ export async function activate(context: ExtensionContext) { setContextValue(IN_BIOME_PROJECT, true); commands.registerCommand(Commands.UpdateBiome, async (version: string) => { - console.log(version); const result = await window.showInformationMessage( `Are you sure you want to update Biome (bundled) to ${version} ?`, { @@ -141,6 +141,11 @@ export async function activate(context: ExtensionContext) { } }); + commands.registerCommand(Commands.ChangeVersion, async () => { + await selectAndDownload(context); + statusBar.checkForUpdates(); + }); + session.registerCommand(Commands.SyntaxTree, syntaxTree(session)); session.registerCommand(Commands.ServerStatus, () => { traceOutputChannel.show(); diff --git a/src/statusBar.ts b/src/statusBar.ts index 486bc598..26c18f4c 100644 --- a/src/statusBar.ts +++ b/src/statusBar.ts @@ -144,6 +144,15 @@ export class StatusBar { } } + if (this.usingBundledBiome) { + this.statusBarItem.command = { + title: "Change bundled Biome version", + command: Commands.ChangeVersion, + }; + } else { + this.statusBarItem.command = Commands.ServerStatus; + } + this.statusBarItem.show(); } @@ -182,5 +191,7 @@ export class StatusBar { } else { this.statusBarUpdateItem.hide(); } + + this.update(); } } From b2023e21720bb4089550bebe1bbdab725a8c91ad Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Fri, 3 Nov 2023 16:42:49 +0100 Subject: [PATCH 05/16] stop server before replacing binary --- src/commands/index.ts | 2 ++ src/downloader.ts | 2 ++ src/main.ts | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/src/commands/index.ts b/src/commands/index.ts index 2c242c52..beffae9a 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -1,5 +1,7 @@ // list of commands available in the VS Code extension export enum Commands { + StopServer = "biome.stopServer", + StartServer = "biome.startServer", RestartLspServer = "biome.restartLspServer", SyntaxTree = "biome.syntaxTree", ServerStatus = "biome.serverStatus", diff --git a/src/downloader.ts b/src/downloader.ts index a53d710d..d46a2935 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -33,6 +33,7 @@ export const selectAndDownload = async (context: ExtensionContext) => { cancellable: false, }, async () => { + await commands.executeCommand(Commands.StopServer); await download(version, context); await commands.executeCommand(Commands.RestartLspServer); }, @@ -49,6 +50,7 @@ export const updateToLatest = async (context: ExtensionContext) => { async () => { const versions = await getVersions(context); const version = versions[0]; + await commands.executeCommand(Commands.StopServer); await download(version, context); await commands.executeCommand(Commands.RestartLspServer); }, diff --git a/src/main.ts b/src/main.ts index 198db789..ff0dda4c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -150,6 +150,13 @@ export async function activate(context: ExtensionContext) { session.registerCommand(Commands.ServerStatus, () => { traceOutputChannel.show(); }); + session.registerCommand(Commands.StopServer, async () => { + try { + await client.stop(); + } catch (error) { + client.error("Stopping client failed", error, "force"); + } + }); session.registerCommand(Commands.RestartLspServer, async () => { try { if (client.isRunning()) { From f591f013efc32e18461dad2c3617a527f9c122f6 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Fri, 3 Nov 2023 17:50:49 +0100 Subject: [PATCH 06/16] handled aborted version selection --- src/commands/index.ts | 1 - src/downloader.ts | 8 ++++++-- src/main.ts | 22 ++++++++++++++-------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/commands/index.ts b/src/commands/index.ts index beffae9a..5fe77077 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -1,7 +1,6 @@ // list of commands available in the VS Code extension export enum Commands { StopServer = "biome.stopServer", - StartServer = "biome.startServer", RestartLspServer = "biome.restartLspServer", SyntaxTree = "biome.syntaxTree", ServerStatus = "biome.serverStatus", diff --git a/src/downloader.ts b/src/downloader.ts index d46a2935..7257f03e 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -1,7 +1,7 @@ import { chmodSync } from "node:fs"; import { Octokit } from "octokit"; import { ofetch } from "ofetch"; -import { coerce, gt, gte, rcompare } from "semver"; +import { coerce, rcompare } from "semver"; import { ExtensionContext, ProgressLocation, @@ -26,6 +26,10 @@ export const selectAndDownload = async (context: ExtensionContext) => { const version = await askVersion(versions); + if (!version) { + return undefined; + } + await window.withProgress( { location: ProgressLocation.Notification, @@ -121,7 +125,7 @@ const download = async (version: string, context: ExtensionContext) => { /** * Display the VS Code prompt for selection the version */ -const askVersion = async (versions: string[]): Promise => { +const askVersion = async (versions: string[]): Promise => { const options = versions.map((version, index) => ({ label: version, description: index === 0 ? "(latest)" : "", diff --git a/src/main.ts b/src/main.ts index ff0dda4c..ae8ad67f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -37,6 +37,17 @@ const resolveAsync = promisify( let client: LanguageClient; +commands.registerCommand(Commands.StopServer, async () => { + if (!client) { + return; + } + try { + await client.stop(); + } catch (error) { + client.error("Stopping client failed", error, "force"); + } +}); + const IN_BIOME_PROJECT = "inBiomeProject"; export async function activate(context: ExtensionContext) { @@ -74,7 +85,9 @@ export async function activate(context: ExtensionContext) { ); if (action === "Download Biome") { - await selectAndDownload(context); + if (!(await selectAndDownload(context))) { + return; + } } server = await getServerPath(context, outputChannel); @@ -150,13 +163,6 @@ export async function activate(context: ExtensionContext) { session.registerCommand(Commands.ServerStatus, () => { traceOutputChannel.show(); }); - session.registerCommand(Commands.StopServer, async () => { - try { - await client.stop(); - } catch (error) { - client.error("Stopping client failed", error, "force"); - } - }); session.registerCommand(Commands.RestartLspServer, async () => { try { if (client.isRunning()) { From 08bf56f639ba9f1fe9e2ccb3ff24427c3c5abcd2 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Fri, 3 Nov 2023 18:17:22 +0100 Subject: [PATCH 07/16] polyfill fetch --- src/downloader.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/downloader.ts b/src/downloader.ts index 7257f03e..f749c143 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -1,6 +1,6 @@ import { chmodSync } from "node:fs"; import { Octokit } from "octokit"; -import { ofetch } from "ofetch"; +import { fetch, ofetch } from "ofetch"; import { coerce, rcompare } from "semver"; import { ExtensionContext, @@ -68,7 +68,11 @@ export const updateToLatest = async (context: ExtensionContext) => { */ const download = async (version: string, context: ExtensionContext) => { // Find the correct asset to download - const octokit = new Octokit(); + const octokit = new Octokit({ + request: { + fetch: fetch, + }, + }); const release = await octokit.request( "GET /repos/{owner}/{repo}/releases/tags/{tag}", @@ -156,7 +160,11 @@ export const getVersions = async ( return cachedVersions.versions; } - const octokit = new Octokit(); + const octokit = new Octokit({ + request: { + fetch: fetch, + }, + }); // Retrieve all tags on the biome repository const tags = await octokit.request("GET /repos/{owner}/{repo}/tags", { From b59d9fea2abd35b955f3bb283b6cab221ccf0dab Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Fri, 3 Nov 2023 18:51:22 +0100 Subject: [PATCH 08/16] register restart command earlier --- src/downloader.ts | 2 +- src/main.ts | 29 ++++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/downloader.ts b/src/downloader.ts index f749c143..b38b5e6f 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -33,7 +33,7 @@ export const selectAndDownload = async (context: ExtensionContext) => { await window.withProgress( { location: ProgressLocation.Notification, - title: `Updating Biome to ${version}`, + title: `Downloading Biome ${version}`, cancellable: false, }, async () => { diff --git a/src/main.ts b/src/main.ts index ae8ad67f..3de1e6cc 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,11 +1,10 @@ import { type ChildProcess, spawn } from "child_process"; import { type Socket, connect } from "net"; import { dirname, isAbsolute } from "path"; -import { TextDecoder, promisify } from "util"; +import { promisify } from "util"; import { ExtensionContext, OutputChannel, - ProgressLocation, TextEditor, Uri, commands, @@ -48,6 +47,21 @@ commands.registerCommand(Commands.StopServer, async () => { } }); +commands.registerCommand(Commands.RestartLspServer, async () => { + if (!client) { + return; + } + try { + if (client.isRunning()) { + await client.restart(); + } else { + await client.start(); + } + } catch (error) { + client.error("Restarting client failed", error, "force"); + } +}); + const IN_BIOME_PROJECT = "inBiomeProject"; export async function activate(context: ExtensionContext) { @@ -163,17 +177,6 @@ export async function activate(context: ExtensionContext) { session.registerCommand(Commands.ServerStatus, () => { traceOutputChannel.show(); }); - session.registerCommand(Commands.RestartLspServer, async () => { - try { - if (client.isRunning()) { - await client.restart(); - } else { - await client.start(); - } - } catch (error) { - client.error("Restarting client failed", error, "force"); - } - }); context.subscriptions.push( client.onDidChangeState((evt) => { From 3db726abea51e0f9fa2ada935fc966b1bb3a2735 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Fri, 3 Nov 2023 19:06:42 +0100 Subject: [PATCH 09/16] fix downloader --- src/downloader.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/downloader.ts b/src/downloader.ts index b38b5e6f..5b408c0a 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -12,7 +12,9 @@ import { } from "vscode"; import { Commands } from "./commands"; -export const selectAndDownload = async (context: ExtensionContext) => { +export const selectAndDownload = async ( + context: ExtensionContext, +): Promise => { const versions = await window.withProgress( { location: ProgressLocation.Notification, @@ -30,7 +32,7 @@ export const selectAndDownload = async (context: ExtensionContext) => { return undefined; } - await window.withProgress( + return await window.withProgress( { location: ProgressLocation.Notification, title: `Downloading Biome ${version}`, @@ -39,7 +41,10 @@ export const selectAndDownload = async (context: ExtensionContext) => { async () => { await commands.executeCommand(Commands.StopServer); await download(version, context); + console.log("Downloaded"); await commands.executeCommand(Commands.RestartLspServer); + console.log("Restarted"); + return version; }, ); }; From 8a2b5098922c9d600c6ff7d97f34a72e28e7b9d5 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Fri, 3 Nov 2023 19:07:03 +0100 Subject: [PATCH 10/16] remove logs --- src/downloader.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/downloader.ts b/src/downloader.ts index 5b408c0a..21eba0e7 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -41,9 +41,7 @@ export const selectAndDownload = async ( async () => { await commands.executeCommand(Commands.StopServer); await download(version, context); - console.log("Downloaded"); await commands.executeCommand(Commands.RestartLspServer); - console.log("Restarted"); return version; }, ); From c5d6fc8b4834c81a8deec99a934c0d0f7a960ed4 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Sat, 4 Nov 2023 18:27:38 +0100 Subject: [PATCH 11/16] do not attempt to fetch if asset does not exist --- src/downloader.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/downloader.ts b/src/downloader.ts index 21eba0e7..dab665df 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -99,6 +99,7 @@ const download = async (version: string, context: ExtensionContext) => { window.showErrorMessage( `The specified version is not available for your platform/architecture (${platformArch}).`, ); + return; } const bin = await ofetch(asset.browser_download_url, { From 621a67e4b3215c2cc3594fa1d65197feb9236033 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Sat, 4 Nov 2023 18:31:33 +0100 Subject: [PATCH 12/16] abort if asset download fails --- src/downloader.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/downloader.ts b/src/downloader.ts index dab665df..d8614dbe 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -102,9 +102,17 @@ const download = async (version: string, context: ExtensionContext) => { return; } - const bin = await ofetch(asset.browser_download_url, { - responseType: "arrayBuffer", - }); + let bin: ArrayBuffer; + try { + bin = await ofetch(asset.browser_download_url, { + responseType: "arrayBuffer", + }); + } catch { + window.showErrorMessage( + `Could not download the binary for your platform/architecture (${platformArch}).`, + ); + return; + } // Write binary file to disk await workspace.fs.writeFile( From cc3e1654c7393c99322c094c2ce86ba80a8b3a0a Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Sat, 4 Nov 2023 18:32:35 +0100 Subject: [PATCH 13/16] rename CLI to binary --- src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 3de1e6cc..6551310a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -93,7 +93,7 @@ export async function activate(context: ExtensionContext) { if (!server.command) { const action = await window.showWarningMessage( - "Could not find Biome in your dependencies. Either add the @biomejs/biome package to your dependencies, or download the Biome CLI.", + "Could not find Biome in your dependencies. Either add the @biomejs/biome package to your dependencies, or download the Biome binary.", "Ok", "Download Biome", ); From 5dc3992d108e817807d623cf5b22534599b91580 Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Sun, 5 Nov 2023 17:17:56 +0100 Subject: [PATCH 14/16] add helper to clear versions cache --- package.json | 5 +++++ src/main.ts | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/package.json b/package.json index e42d7c74..91298527 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,11 @@ "command": "biome.restartLspServer", "title": "Restart LSP Server", "category": "Biome" + }, + { + "command": "biome.clearVersionsCache", + "title": "Clear versions cache", + "category": "Biome" } ], "menus": { diff --git a/src/main.ts b/src/main.ts index 6551310a..7d94d693 100644 --- a/src/main.ts +++ b/src/main.ts @@ -72,6 +72,10 @@ export async function activate(context: ExtensionContext) { .getConfiguration("biome") .get("requireConfiguration"); + commands.registerCommand("biome.clearVersionsCache", async () => { + await context.globalState.update("biome_versions_cache", undefined); + }); + // If the extension requires a configuration file to be present, we attempt to // locate it. If a config file cannot be found, we do not go any further. if (requiresConfiguration) { From 154d797dd4c21e164a6e6dba4a3f10f61f9e913e Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Sun, 5 Nov 2023 17:19:52 +0100 Subject: [PATCH 15/16] replace ofetch and octokit by undici --- package.json | 3 +- pnpm-lock.yaml | 442 ++-------------------------------------------- src/downloader.ts | 61 +++---- 3 files changed, 38 insertions(+), 468 deletions(-) diff --git a/package.json b/package.json index 91298527..e3aa4159 100644 --- a/package.json +++ b/package.json @@ -161,10 +161,9 @@ "typescript": "^5.1.6" }, "dependencies": { - "octokit": "^3.1.1", - "ofetch": "^1.3.3", "resolve": "^1.22.4", "semver": "^7.5.4", + "undici": "^5.27.2", "vscode-languageclient": "^8.1.0" }, "vsce": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 790414f8..a56c8ac3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,18 +5,15 @@ settings: excludeLinksFromLockfile: false dependencies: - octokit: - specifier: ^3.1.1 - version: 3.1.1 - ofetch: - specifier: ^1.3.3 - version: 1.3.3 resolve: specifier: ^1.22.4 version: 1.22.4 semver: specifier: ^7.5.4 version: 7.5.4 + undici: + specifier: ^5.27.2 + version: 5.27.2 vscode-languageclient: specifier: ^8.1.0 version: 8.1.0 @@ -315,270 +312,14 @@ packages: dev: true optional: true - /@octokit/app@14.0.1: - resolution: {integrity: sha512-4opdXcWBVhzd6FOxlaxDKXXqi9Vz2hsDSWQGNo49HbYFAX11UqMpksMjEdfvHy0x19Pse8Nvn+R6inNb/V398w==} - engines: {node: '>= 18'} - dependencies: - '@octokit/auth-app': 6.0.1 - '@octokit/auth-unauthenticated': 5.0.1 - '@octokit/core': 5.0.1 - '@octokit/oauth-app': 6.0.0 - '@octokit/plugin-paginate-rest': 9.1.2(@octokit/core@5.0.1) - '@octokit/types': 12.1.1 - '@octokit/webhooks': 12.0.3 - dev: false - - /@octokit/auth-app@6.0.1: - resolution: {integrity: sha512-tjCD4nzQNZgmLH62+PSnTF6eGerisFgV4v6euhqJik6yWV96e1ZiiGj+NXIqbgnpjLmtnBqVUrNyGKu3DoGEGA==} - engines: {node: '>= 18'} - dependencies: - '@octokit/auth-oauth-app': 7.0.1 - '@octokit/auth-oauth-user': 4.0.1 - '@octokit/request': 8.1.4 - '@octokit/request-error': 5.0.1 - '@octokit/types': 12.1.1 - deprecation: 2.3.1 - lru-cache: 10.0.1 - universal-github-app-jwt: 1.1.1 - universal-user-agent: 6.0.0 - dev: false - - /@octokit/auth-oauth-app@7.0.1: - resolution: {integrity: sha512-RE0KK0DCjCHXHlQBoubwlLijXEKfhMhKm9gO56xYvFmP1QTMb+vvwRPmQLLx0V+5AvV9N9I3lr1WyTzwL3rMDg==} - engines: {node: '>= 18'} - dependencies: - '@octokit/auth-oauth-device': 6.0.1 - '@octokit/auth-oauth-user': 4.0.1 - '@octokit/request': 8.1.4 - '@octokit/types': 12.1.1 - '@types/btoa-lite': 1.0.1 - btoa-lite: 1.0.0 - universal-user-agent: 6.0.0 - dev: false - - /@octokit/auth-oauth-device@6.0.1: - resolution: {integrity: sha512-yxU0rkL65QkjbqQedgVx3gmW7YM5fF+r5uaSj9tM/cQGVqloXcqP2xK90eTyYvl29arFVCW8Vz4H/t47mL0ELw==} - engines: {node: '>= 18'} - dependencies: - '@octokit/oauth-methods': 4.0.0 - '@octokit/request': 8.1.4 - '@octokit/types': 12.1.1 - universal-user-agent: 6.0.0 - dev: false - - /@octokit/auth-oauth-user@4.0.1: - resolution: {integrity: sha512-N94wWW09d0hleCnrO5wt5MxekatqEJ4zf+1vSe8MKMrhZ7gAXKFOKrDEZW2INltvBWJCyDUELgGRv8gfErH1Iw==} - engines: {node: '>= 18'} - dependencies: - '@octokit/auth-oauth-device': 6.0.1 - '@octokit/oauth-methods': 4.0.0 - '@octokit/request': 8.1.4 - '@octokit/types': 12.1.1 - btoa-lite: 1.0.0 - universal-user-agent: 6.0.0 - dev: false - - /@octokit/auth-token@4.0.0: - resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} - engines: {node: '>= 18'} - dev: false - - /@octokit/auth-unauthenticated@5.0.1: - resolution: {integrity: sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==} - engines: {node: '>= 18'} - dependencies: - '@octokit/request-error': 5.0.1 - '@octokit/types': 12.1.1 - dev: false - - /@octokit/core@5.0.1: - resolution: {integrity: sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==} - engines: {node: '>= 18'} - dependencies: - '@octokit/auth-token': 4.0.0 - '@octokit/graphql': 7.0.2 - '@octokit/request': 8.1.4 - '@octokit/request-error': 5.0.1 - '@octokit/types': 12.1.1 - before-after-hook: 2.2.3 - universal-user-agent: 6.0.0 - dev: false - - /@octokit/endpoint@9.0.2: - resolution: {integrity: sha512-qhKW8YLIi+Kmc92FQUFGr++DYtkx/1fBv+Thua6baqnjnOsgBYJDCvWZR1YcINuHGOEQt416WOfE+A/oG60NBQ==} - engines: {node: '>= 18'} - dependencies: - '@octokit/types': 12.1.1 - is-plain-object: 5.0.0 - universal-user-agent: 6.0.0 - dev: false - - /@octokit/graphql@7.0.2: - resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==} - engines: {node: '>= 18'} - dependencies: - '@octokit/request': 8.1.4 - '@octokit/types': 12.1.1 - universal-user-agent: 6.0.0 - dev: false - - /@octokit/oauth-app@6.0.0: - resolution: {integrity: sha512-bNMkS+vJ6oz2hCyraT9ZfTpAQ8dZNqJJQVNaKjPLx4ue5RZiFdU1YWXguOPR8AaSHS+lKe+lR3abn2siGd+zow==} - engines: {node: '>= 18'} - dependencies: - '@octokit/auth-oauth-app': 7.0.1 - '@octokit/auth-oauth-user': 4.0.1 - '@octokit/auth-unauthenticated': 5.0.1 - '@octokit/core': 5.0.1 - '@octokit/oauth-authorization-url': 6.0.2 - '@octokit/oauth-methods': 4.0.0 - '@types/aws-lambda': 8.10.125 - universal-user-agent: 6.0.0 - dev: false - - /@octokit/oauth-authorization-url@6.0.2: - resolution: {integrity: sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA==} - engines: {node: '>= 18'} - dev: false - - /@octokit/oauth-methods@4.0.0: - resolution: {integrity: sha512-dqy7BZLfLbi3/8X8xPKUKZclMEK9vN3fK5WF3ortRvtplQTszFvdAGbTo71gGLO+4ZxspNiLjnqdd64Chklf7w==} - engines: {node: '>= 18'} - dependencies: - '@octokit/oauth-authorization-url': 6.0.2 - '@octokit/request': 8.1.4 - '@octokit/request-error': 5.0.1 - '@octokit/types': 11.1.0 - btoa-lite: 1.0.0 - dev: false - - /@octokit/openapi-types@18.1.1: - resolution: {integrity: sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==} - dev: false - - /@octokit/openapi-types@19.0.2: - resolution: {integrity: sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ==} - dev: false - - /@octokit/plugin-paginate-graphql@4.0.0(@octokit/core@5.0.1): - resolution: {integrity: sha512-7HcYW5tP7/Z6AETAPU14gp5H5KmCPT3hmJrS/5tO7HIgbwenYmgw4OY9Ma54FDySuxMwD+wsJlxtuGWwuZuItA==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': '>=5' - dependencies: - '@octokit/core': 5.0.1 - dev: false - - /@octokit/plugin-paginate-rest@9.1.2(@octokit/core@5.0.1): - resolution: {integrity: sha512-euDbNV6fxX6btsCDnZoZM4vw3zO1nj1Z7TskHAulO6mZ9lHoFTpwll6farf+wh31mlBabgU81bBYdflp0GLVAQ==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': '>=5' - dependencies: - '@octokit/core': 5.0.1 - '@octokit/types': 12.1.1 - dev: false - - /@octokit/plugin-rest-endpoint-methods@10.1.2(@octokit/core@5.0.1): - resolution: {integrity: sha512-JztgZ82CY4JNlPTuF0jh4iWuuGpEi5czFCoXyAbMg4F2XyFBbG5DWAKfa3odRvdZww6Df1tQgBKnqpd9X0WF9g==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': '>=5' - dependencies: - '@octokit/core': 5.0.1 - '@octokit/types': 12.1.1 - dev: false - - /@octokit/plugin-retry@6.0.1(@octokit/core@5.0.1): - resolution: {integrity: sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': '>=5' - dependencies: - '@octokit/core': 5.0.1 - '@octokit/request-error': 5.0.1 - '@octokit/types': 12.1.1 - bottleneck: 2.19.5 - dev: false - - /@octokit/plugin-throttling@8.1.2(@octokit/core@5.0.1): - resolution: {integrity: sha512-oFba+ioR6HGb0fgqxMta7Kpk/MdffUTuUxNY856l1nXPvh7Qggp8w4AksRx1SDA8SGd+4cbrpkY4k1J/Xz8nZQ==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': ^5.0.0 - dependencies: - '@octokit/core': 5.0.1 - '@octokit/types': 12.1.1 - bottleneck: 2.19.5 - dev: false - - /@octokit/request-error@5.0.1: - resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==} - engines: {node: '>= 18'} - dependencies: - '@octokit/types': 12.1.1 - deprecation: 2.3.1 - once: 1.4.0 - dev: false - - /@octokit/request@8.1.4: - resolution: {integrity: sha512-M0aaFfpGPEKrg7XoA/gwgRvc9MSXHRO2Ioki1qrPDbl1e9YhjIwVoHE7HIKmv/m3idzldj//xBujcFNqGX6ENA==} - engines: {node: '>= 18'} - dependencies: - '@octokit/endpoint': 9.0.2 - '@octokit/request-error': 5.0.1 - '@octokit/types': 12.1.1 - is-plain-object: 5.0.0 - universal-user-agent: 6.0.0 - dev: false - - /@octokit/types@11.1.0: - resolution: {integrity: sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==} - dependencies: - '@octokit/openapi-types': 18.1.1 - dev: false - - /@octokit/types@12.1.1: - resolution: {integrity: sha512-qnJTldJ1NyGT5MTsCg/Zi+y2IFHZ1Jo5+njNCjJ9FcainV7LjuHgmB697kA0g4MjZeDAJsM3B45iqCVsCLVFZg==} - dependencies: - '@octokit/openapi-types': 19.0.2 - dev: false - - /@octokit/webhooks-methods@4.0.0: - resolution: {integrity: sha512-M8mwmTXp+VeolOS/kfRvsDdW+IO0qJ8kYodM/sAysk093q6ApgmBXwK1ZlUvAwXVrp/YVHp6aArj4auAxUAOFw==} - engines: {node: '>= 18'} - dev: false - - /@octokit/webhooks-types@7.1.0: - resolution: {integrity: sha512-y92CpG4kFFtBBjni8LHoV12IegJ+KFxLgKRengrVjKmGE5XMeCuGvlfRe75lTRrgXaG6XIWJlFpIDTlkoJsU8w==} - dev: false - - /@octokit/webhooks@12.0.3: - resolution: {integrity: sha512-8iG+/yza7hwz1RrQ7i7uGpK2/tuItZxZq1aTmeg2TNp2xTUB8F8lZF/FcZvyyAxT8tpDMF74TjFGCDACkf1kAQ==} - engines: {node: '>= 18'} - dependencies: - '@octokit/request-error': 5.0.1 - '@octokit/webhooks-methods': 4.0.0 - '@octokit/webhooks-types': 7.1.0 - aggregate-error: 3.1.0 - dev: false - - /@types/aws-lambda@8.10.125: - resolution: {integrity: sha512-Vqw/WMlV4O1fJT6capim01v7VLDZkcX1n6Yhb52E7IfnMqYbNfwHfyDV8rRN42NLBtdDvfaqcCqs2K0fr5ljZw==} - dev: false - - /@types/btoa-lite@1.0.1: - resolution: {integrity: sha512-YwCjy5v1THSaj5KrBz0SKwKYtjwT0YpOm8VB4TR6DzyvTa503T+rE0Ku6Q3DUKtm1rzNrEXyqdYHpcLiYN6oXg==} - dev: false - - /@types/jsonwebtoken@9.0.4: - resolution: {integrity: sha512-8UYapdmR0QlxgvJmyE8lP7guxD0UGVMfknsdtCFZh4ovShdBl3iOI4zdvqBHrB/IS+xUj3PSx73Qkey1fhWz+g==} - dependencies: - '@types/node': 18.17.5 + /@fastify/busboy@2.0.0: + resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==} + engines: {node: '>=14'} dev: false /@types/node@18.17.5: resolution: {integrity: sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==} + dev: true /@types/resolve@1.20.2: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -621,14 +362,6 @@ packages: keytar: 7.9.0 dev: true - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: false - /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -656,10 +389,6 @@ packages: dev: true optional: true - /before-after-hook@2.2.3: - resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} - dev: false - /bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} requiresBuild: true @@ -674,10 +403,6 @@ packages: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true - /bottleneck@2.19.5: - resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} - dev: false - /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -691,18 +416,10 @@ packages: balanced-match: 1.0.2 dev: false - /btoa-lite@1.0.0: - resolution: {integrity: sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==} - dev: false - /buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} dev: true - /buffer-equal-constant-time@1.0.1: - resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} - dev: false - /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} requiresBuild: true @@ -758,11 +475,6 @@ packages: dev: true optional: true - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: false - /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -813,14 +525,6 @@ packages: dev: true optional: true - /deprecation@2.3.1: - resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} - dev: false - - /destr@2.0.2: - resolution: {integrity: sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==} - dev: false - /detect-libc@2.0.2: resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} engines: {node: '>=8'} @@ -855,12 +559,6 @@ packages: domhandler: 5.0.3 dev: true - /ecdsa-sig-formatter@1.0.11: - resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} - dependencies: - safe-buffer: 5.2.1 - dev: false - /end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} requiresBuild: true @@ -1008,11 +706,6 @@ packages: dev: true optional: true - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: false - /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: @@ -1036,46 +729,10 @@ packages: has: 1.0.3 dev: false - /is-plain-object@5.0.0: - resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} - engines: {node: '>=0.10.0'} - dev: false - /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} dev: true - /jsonwebtoken@9.0.2: - resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} - engines: {node: '>=12', npm: '>=6'} - dependencies: - jws: 3.2.2 - 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.5.4 - dev: false - - /jwa@1.4.1: - resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} - dependencies: - buffer-equal-constant-time: 1.0.1 - ecdsa-sig-formatter: 1.0.11 - safe-buffer: 5.2.1 - dev: false - - /jws@3.2.2: - resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} - dependencies: - jwa: 1.4.1 - safe-buffer: 5.2.1 - dev: false - /keytar@7.9.0: resolution: {integrity: sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==} requiresBuild: true @@ -1096,39 +753,6 @@ packages: uc.micro: 1.0.6 dev: true - /lodash.includes@4.3.0: - resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} - dev: false - - /lodash.isboolean@3.0.3: - resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} - dev: false - - /lodash.isinteger@4.0.4: - resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} - dev: false - - /lodash.isnumber@3.0.3: - resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} - dev: false - - /lodash.isplainobject@4.0.6: - resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - dev: false - - /lodash.isstring@4.0.1: - resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} - dev: false - - /lodash.once@4.1.1: - resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} - dev: false - - /lru-cache@10.0.1: - resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==} - engines: {node: 14 || >=16.14} - dev: false - /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -1188,10 +812,6 @@ packages: dev: true optional: true - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: false - /mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} dev: true @@ -1217,10 +837,6 @@ packages: dev: true optional: true - /node-fetch-native@1.4.1: - resolution: {integrity: sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w==} - dev: false - /nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} dependencies: @@ -1231,34 +847,11 @@ packages: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} dev: true - /octokit@3.1.1: - resolution: {integrity: sha512-AKJs5XYs7iAh7bskkYpxhUIpsYZdLqjnlnqrN5s9FFZuJ/a6ATUHivGpUKDpGB/xa+LGDtG9Lu8bOCfPM84vHQ==} - engines: {node: '>= 18'} - dependencies: - '@octokit/app': 14.0.1 - '@octokit/core': 5.0.1 - '@octokit/oauth-app': 6.0.0 - '@octokit/plugin-paginate-graphql': 4.0.0(@octokit/core@5.0.1) - '@octokit/plugin-paginate-rest': 9.1.2(@octokit/core@5.0.1) - '@octokit/plugin-rest-endpoint-methods': 10.1.2(@octokit/core@5.0.1) - '@octokit/plugin-retry': 6.0.1(@octokit/core@5.0.1) - '@octokit/plugin-throttling': 8.1.2(@octokit/core@5.0.1) - '@octokit/request-error': 5.0.1 - '@octokit/types': 12.1.1 - dev: false - - /ofetch@1.3.3: - resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==} - dependencies: - destr: 2.0.2 - node-fetch-native: 1.4.1 - ufo: 1.3.1 - dev: false - /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 + dev: true /parse-semver@1.1.1: resolution: {integrity: sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==} @@ -1378,6 +971,8 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} requiresBuild: true + dev: true + optional: true /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -1508,23 +1103,15 @@ packages: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} dev: true - /ufo@1.3.1: - resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==} - dev: false - /underscore@1.13.6: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} dev: true - /universal-github-app-jwt@1.1.1: - resolution: {integrity: sha512-G33RTLrIBMFmlDV4u4CBF7dh71eWwykck4XgaxaIVeZKOYZRAAxvcGMRFTUclVY6xoUPQvO4Ne5wKGxYm/Yy9w==} + /undici@5.27.2: + resolution: {integrity: sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==} + engines: {node: '>=14.0'} dependencies: - '@types/jsonwebtoken': 9.0.4 - jsonwebtoken: 9.0.2 - dev: false - - /universal-user-agent@6.0.0: - resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} + '@fastify/busboy': 2.0.0 dev: false /url-join@4.0.1: @@ -1564,6 +1151,7 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true /xml2js@0.5.0: resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} diff --git a/src/downloader.ts b/src/downloader.ts index d8614dbe..0ced4678 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -1,7 +1,6 @@ import { chmodSync } from "node:fs"; -import { Octokit } from "octokit"; -import { fetch, ofetch } from "ofetch"; import { coerce, rcompare } from "semver"; +import { fetch } from "undici"; import { ExtensionContext, ProgressLocation, @@ -70,26 +69,18 @@ export const updateToLatest = async (context: ExtensionContext) => { * @param version The version to download */ const download = async (version: string, context: ExtensionContext) => { - // Find the correct asset to download - const octokit = new Octokit({ - request: { - fetch: fetch, - }, - }); - - const release = await octokit.request( - "GET /repos/{owner}/{repo}/releases/tags/{tag}", - { - owner: "biomejs", - repo: "biome", - tag: `cli/v${version}`, - }, - ); + const releases = (await ( + await fetch( + `https://api.github.com/repos/biomejs/biome/releases/tags/cli/v${version}`, + ) + ).json()) as { + assets: { name: string; browser_download_url: string }[]; + }; const platformArch = `${process.platform}-${process.arch}`; // Find the asset for the current platform - const asset = release.data.assets.find( + const asset = releases.assets.find( (asset) => asset.name === `biome-${platformArch}${process.platform === "win32" ? ".exe" : ""}`, @@ -104,9 +95,8 @@ const download = async (version: string, context: ExtensionContext) => { let bin: ArrayBuffer; try { - bin = await ofetch(asset.browser_download_url, { - responseType: "arrayBuffer", - }); + const blob = await fetch(asset.browser_download_url); + bin = await blob.arrayBuffer(); } catch { window.showErrorMessage( `Could not download the binary for your platform/architecture (${platformArch}).`, @@ -172,26 +162,19 @@ export const getVersions = async ( return cachedVersions.versions; } - const octokit = new Octokit({ - request: { - fetch: fetch, - }, - }); - - // Retrieve all tags on the biome repository - const tags = await octokit.request("GET /repos/{owner}/{repo}/tags", { - owner: "biomejs", - repo: "biome", - per_page: 50, - }); + const releases = (await ( + await fetch( + "https://api.github.com/repos/biomejs/biome/releases?per_page=100", + ) + ).json()) as { tag_name: string }[]; - const versions = tags.data - .filter((tag) => tag.name.startsWith("cli/")) - .map((tag) => tag.name.replace("cli/", "")) - .map((tag) => coerce(tag)) + const versions = releases + .filter((release) => release.tag_name.startsWith("cli/")) + .map((release) => release.tag_name.replace("cli/", "")) + .map((release) => coerce(release)) .sort((a, b) => rcompare(a, b)) - .filter((tag) => tag?.version !== null) - .map((tag) => tag?.version); + .filter((release) => release?.version !== null) + .map((release) => release?.version); // Cache the result for 1 hour await context.globalState.update("biome_versions_cache", { From acb62f2a9fd65c2a691f81efa73931baf699c6ea Mon Sep 17 00:00:00 2001 From: Nicolas Hedger Date: Sun, 5 Nov 2023 17:20:49 +0100 Subject: [PATCH 16/16] move command registration inside activate --- src/main.ts | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main.ts b/src/main.ts index 7d94d693..80e9726f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -36,32 +36,6 @@ const resolveAsync = promisify( let client: LanguageClient; -commands.registerCommand(Commands.StopServer, async () => { - if (!client) { - return; - } - try { - await client.stop(); - } catch (error) { - client.error("Stopping client failed", error, "force"); - } -}); - -commands.registerCommand(Commands.RestartLspServer, async () => { - if (!client) { - return; - } - try { - if (client.isRunning()) { - await client.restart(); - } else { - await client.start(); - } - } catch (error) { - client.error("Restarting client failed", error, "force"); - } -}); - const IN_BIOME_PROJECT = "inBiomeProject"; export async function activate(context: ExtensionContext) { @@ -72,6 +46,32 @@ export async function activate(context: ExtensionContext) { .getConfiguration("biome") .get("requireConfiguration"); + commands.registerCommand(Commands.StopServer, async () => { + if (!client) { + return; + } + try { + await client.stop(); + } catch (error) { + client.error("Stopping client failed", error, "force"); + } + }); + + commands.registerCommand(Commands.RestartLspServer, async () => { + if (!client) { + return; + } + try { + if (client.isRunning()) { + await client.restart(); + } else { + await client.start(); + } + } catch (error) { + client.error("Restarting client failed", error, "force"); + } + }); + commands.registerCommand("biome.clearVersionsCache", async () => { await context.globalState.update("biome_versions_cache", undefined); });